Le modificateur synchronized permet de contrôler l'accès aux objets partagés dans un environnement multi-threads.
Ce modificateur permet d'éviter que plusieurs unités d'exécution (ou threads) puissent accéder simultanément au même objet.
Pour qu'une classe Java soit utilisable en multi-tâches, il est nécessaire qu'elle possède des méthodes synchronized.
En fait, toutes les méthodes de tous les objets doivent être synchronisées pour une utilisation correcte de l'objet dans un environnement multi-threads.
synchronized objet synchronized (expression){ ... } public void nomMethode(String[] tableau) { synchronized (tableau){ // Instructions... } ... }
Dans le cas d'un bloc d'instructions synchronisé, l'objet adéquat est l'argument entre les paranthèses.
Une méthode synchronisée permet d'appliquer un dispositif de verrouillage sur un objet ou sur une classe à partir duquel, elle est appelée.
void synchronized nomMethode(){ ... } //est équivalent à void nomMethode(){ synchronized (this){ ... } }
Dans le cas d'une méthode d'instance synchronisée, l'objet adéquat est représenté par le mot-clé this.
Lorsqu'une thread veut exécuter une méthode d'instance portant le modificateur synchronized, Java verrouille l'instance de classe.
Subséquemment, une autre thread invoquant une méthode synchronisée sur ce même objet, sera bloquée tant que que le verrou ne sera pas levé.
class Calculatrice { int x; int y; ... // Ces méthodes synchronisées garantiront que
// les variables x et y ne seront pas modifiées
// durant l'une des opérations public synchronized float addition(){ return x + y; } public synchronized float soustraction(){ return x - y; } public synchronized float multiplication(){ return x * y; } public synchronized float division(){ return x / y; } ... }
De la même façon, si une thread veut exécuter une méthode de classe (static) portant le modificateur synchronized, Java pose un verrou empêchant un autre thread de solliciter une méthode synchronisée de la même classe.
Dans le cas d'une méthode statique synchronisée, l'objet de classe adéquat est l'instance de java.lang.Class définissant cette méthode de classe.
Les méthodes synchronisées ne peuvent pas s'exécuter en concurrence, leur permettant ainsi de maintenir un état stable dans l'entité partagée.
Lorsque l'exécution d'une méthode synchronized se termine de n'importe quelle manière, le verrou est levé et une autre méthode synchronisée peut alors à son tour être exécutée.
class UniteExecution extends Thread { static String message[] = {"Ceci","est","une", "demonstration","de", "Thread","dans","Java."}; public static void main(String args[]){ UniteExecution UE1 = new UniteExecution("Premier Thread : "); UniteExecution UE2 = new UniteExecution("Second Thread : "); UE1.start(); UE2.start(); boolean UE1_actif = true; boolean UE2_actif = true; while(UE1_actif || UE2_actif) { if(UE1_actif && !UE1.isAlive()){ UE1_actif = false; System.out.println("UE 1 est inactif."); } if(UE2_actif && !UE2.isAlive()){ UE2_actif = false; System.out.println("UE 2 est inactif."); } } } public UniteExecution(String chaine){ super(chaine); } public void run(){ synchronized(System.out){ System.out.print(getName()); for(int i = 0; i < message.length; i++) { temporisation(); System.out.print(message[i]); if(i == message.length - 1) System.out.println("n"); else System.out.print(" "); } } } void temporisation(){ try { sleep(800); } catch (InterruptedException x){ System.out.println("Un problème s'est produit !"); } } }