Synchronized

Utilisation du mot clé synchronized

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com

Java, contrairement à PHP, est un langage qui supporte multi-threading (traitement parallel de plusieurs portions de code en temps partagé). Cette spécificité peut être utilisée pour accéler l'exécution du code, effectuer les traitements en tâche de fond. Chaque thread peut être dans un des 4 états :
- nouveau : thread initialisé, mais pas actif
- exécutable : thread est prêt à être lancé (via la méthode start()). Il est exécuté quand le système trouvera les ressources nécessaires.
- en attente : thread est en veille (via une des méthodes sleep() ou wait()), il peut être exécuté à n'importe quel moment
- mort : thread ne s'exécute plus (soit il a sorti de sa méthode run(), soit il a été victime d'une exception non interceptée) [ meilleurs états http://www.tutorialspoint.com/java/java_multithreading.htm ]

On voit bien que plusieurs threads peuvent accéder à des ressources (méthodes, attributs). Cela peut provoquer des modifications inattendues qui peuvent être à l'origine des erreurs. Pour éviter les problèmes de ce nature, Java possède le mot clé synchronized. Il fait en sorte qu'uniquement un thread peut accéder à la ressource synchronisée. Regardons ceci sur un exemple :

afficher le code

Le système nous affiche, malgré la présence du sleep() d'une seconde, tous les résultats s'affichent d'un seul coup. Cependant, la méthode sleep() devrait faire en sorte que les résultats s'affichent un par un, seconde par seconde. Pour voir cela, on utilisera le mot-clé synchronized. Voici le code après le correctif :

afficher le code

Synchronized veut donc dire qu'uniquement un seul thread peut accéder à la ressource synchronisée.

On peut voir le problème de synchronisation sur la base d'un compteur. Notre compteur aura une méthode d'incrementation. Cette fonction affichera dans un premier temps le résultat de l'incrémentation précédente. Ensuite elle incrémentera à son tour cette valeur. Regardon d'abord ce qui se passe si la méthode increment() n'est pas synchronisée :

afficher le code

Sur l'écran on verra que le premier affichage est incorrect :

Before incrementing 49




Before incrementing 50
After incrementing 50


Before incrementing 51
After incrementing 52
After incrementing 51
Before incrementing 50
After incrementing 53

Tout cela parce qu'au moins deux threads accèdent à la resource partagée (en occurence, int counter) en même temps. Si l'on veut éviter ce résultat incohérent, on doit synchroniser l'opération effectuée dans la méthode increment(), en y introduisant un mot clé synchronized. Après ce changement, la classe Counter va se présenter ainsi :

class Counter {
    int counter = 0;
  
    public Counter(int c) {
        counter = c;
    }
  
    public synchronized void increment() {
        System.out.println("\n");
        System.out.println("Before incrementing " + counter);
        counter++;
        System.out.println("After incrementing " + counter);
    }
}

La méthode increment() sera alors synchronisée et uniquement un seul processus pourra effectuer les opérations sur la variable counter. Le résultat sera alors correct. L'incrémentation deviendra une suite logique du chiffre 49, comme ici :

Before incrementing 49
After incrementing 50


Before incrementing 50
After incrementing 51


Before incrementing 51
After incrementing 52


Before incrementing 52
After incrementing 53

Dans le cas synchronisé, on devrait recevoir les résultats montants. Autrement dit, un processus devrait utiliser une nouvelle valeur à incrementer. Cependant, si notre cas n'est pas synchronisé,

Bartosz KONIECZNY Concurrence

Une question ? Une remarque ?

*

*

Moi

Développeur d'applications Internet et journaliste passionné par l'adjectif français. Un aigle polonais orienté vers la progression, volant très haut et écoutant du zouk après les matches du foot français.

Vous appréciez mon travail ?

Pour contribuer au développement de ce site, ou pour remercier pour des articles rédigés, vous pouvez faire un don.

Un conseil Symfony1

Comment appeler un helper dans l'action ?

L'une des méthodes pour utiliser un view helper dans l'action est: sfProjectConfiguration::getActive()->loadHelpers(array("mon_helper")); mon_helper();