Dans la programmation multi-thread, le problème le plus critique et le plus concerné devrait être le problème de synchronisation, ce qui est un point difficile et le noyau.
Du synchronisé et volatile de la première version de JDK à l'interface de verrouillage dans le package java.util.concurrent.locks fourni dans JDK 1.5 (les implémentations incluent Readlock, WriteLock et ReentrantLoc), l'implémentation multi-threading est également progressivement en maïs.
Quel mécanisme est utilisé pour contrôler la synchronisation? La première réaction est le verrouillage, qui aurait dû être exposé lors de l'apprentissage du système d'exploitation et de la base de données. Dans les programmes multi-threads Java, lorsque plusieurs programmes sont en concurrence pour la même ressource, afin d'éviter la corrosion des ressources, le premier thread accédant à la ressource se voit attribuer un verrouillage d'objet et les générations ultérieures doivent attendre la libération de ce verrouillage d'objet.
Oui, la chose la plus inquiet de la synchronisation des threads Java est l'utilisation de ressources partagées.
Comprenons d'abord certaines ressources partagées des threads disponibles.
Depuis le JVM, nous devons coordonner les données partagées par les threads:
1. La variable d'instance enregistrée dans le tas; 2. La variable de classe enregistrée dans la zone de la méthode.
Lorsque la machine virtuelle Java charge une classe, chaque objet ou classe sera associé à un moniteur pour protéger la variable d'instance ou la variable de classe de l'objet; Bien sûr, si l'objet n'a pas de variables d'instance ou si la classe n'a pas de variables, le moniteur ne surveillera rien.
Afin d'atteindre le mutex des moniteurs mentionnés ci-dessus, la machine virtuelle associe un verrou (également appelé verrou invisible) pour chaque objet ou classe. Permettez-moi d'expliquer ici que les verrous de classe sont également implémentés via des verrous d'objets, car lorsque la classe est chargée, le JVM créera une instance de java.lang.class pour chaque classe; Ainsi, lorsque le verrou est contre un objet, l'objet de classe de cette classe est verrouillé.
De plus, un thread peut verrouiller un objet plusieurs fois, ce qui correspond à plusieurs versions; Il s'agit d'une calculatrice de verrouillage fournie par JVM pour chaque verrouillage d'objet. Le dernier verrou est ajouté 1 et le moins 1 correspondant, et lorsque la valeur de la calculatrice est 0, elle est libérée. Ce verrouillage d'objet est utilisé par le moniteur à l'intérieur du JVM et est également généré automatiquement par le JVM. Tous les programmeurs n'ont pas besoin de l'ajouter par eux-mêmes.
Après avoir introduit le principe de synchronisation de Java, nous allons arriver sur le sujet et parler d'abord de l'utilisation de la synchronisation. D'autres synchronisations seront introduites dans les chapitres suivants.
Essayons d'abord d'exécuter un exemple.
package thread_test; / ** * Test des programmes multithreads qui étendent l'implémentation de la classe de thread * * / classe publique TestThread étend Thread {private int threadnum; public TestThread (int threadnum) {this.threadnum = threadnum; } @Override public synchronisé void run () {for (int i = 0; i <1000; i ++) {System.out.println ("no." + Threadnum + ":" + i); }} public static void main (String [] args) lève une exception {pour (int i = 0; i <10; i ++) {new TestThread (i) .Start (); Thread.Sleep (1); }}}
Résultats en cours:
No.0: 887 No.0: 888 No.0: 889 No.0: 890 No.0: 891 No.0: 892 No.0: 893 No.0: 894 No.7: 122 No.7: 123 No.7: 124
Ce qui précède n'est qu'un clip, expliquant un problème.
Si vous faites attention, vous constaterez que n ° 0: 894 est suivi par n ° 7: 122, ce qui signifie qu'il ne commence pas de 0 à 999.
On dit que synchronisé peut implémenter des méthodes de synchronisation ou des blocs de synchronisation, pourquoi ne peut-il pas fonctionner ici?
Analysons d'abord le mécanisme de synchronisation. La synchronisation est obtenue par verrouillage. Donc, dans l'exemple ci-dessus, quel objet est verrouillé ou quelle classe est verrouillée? Il y a deux variables à l'intérieur, l'une est i et l'autre est threadnum; I est interne à la méthode et Threadnum est privé.
Apprenons le mécanisme de course à synchronisation:
Dans un programme Java, lorsque le bloc synchronisé ou la méthode synchronisée est utilisé, cette zone est marquée pour la surveillance; Alors qu'un JVM gère le programme, lorsqu'un programme entre dans la zone de surveillance, il verrouille automatiquement l'objet ou la classe.
Donc, dans l'exemple ci-dessus, qu'est-ce qui est verrouillé après l'utilisation du mot clé synchronisé?
Lors de la méthode synchronisée, verrouillez l'objet d'instance qui appelle la méthode elle-même comme verrouillage d'objet. Dans cet exemple, les 10 threads ont leurs propres objets de classe TestThread, donc le verrouillage d'objet acquis est également son propre verrou d'objet et n'a rien à voir avec d'autres threads.
Pour implémenter le verrouillage de la méthode, les objets partagés doivent être verrouillés.
Changez l'exemple ci-dessus, puis jetez un œil:
package thread_test; / ** * Test des programmes multithreads qui étendent l'implémentation de la classe de thread * * / classe publique TestThread étend Thread {private int threadnum; drapeau de chaîne privé; // Mark Public TestThread (int threadnum, String Flag) {this.threadnum = threadnum; this.flag = drapeau; } @Override public void run () {synchronisé (flag) {for (int i = 0; i <1000; i ++) {System.out.println ("no." + Threadnum + ":" + i); }}} public static void main (String [] args) lève l'exception {String Flag = new String ("Flag"); for (int i = 0; i <10; i ++) {new TestThread (i, drap) .start (); Thread.Sleep (1); }}}
Ceci s'ajoute également un drapeau partagé. Ensuite, l'indicateur est synchronisé à travers le bloc synchronisé; Cela remplit les conditions de verrouillage de l'objet partagé.
Oui, les résultats en cours sont venus en ordre.
Grâce au bloc synchronisé, spécifiez l'acquisition de verrous d'objets pour atteindre la synchronisation. Y a-t-il donc d'autres méthodes qui peuvent être implémentées via la méthode synchronisée?
Selon le principe de synchronisation: si un verrouillage d'objet partagé ou un verrouillage de classe peut être obtenu, la synchronisation peut être obtenue. Pouvons-nous donc y parvenir en partageant un verrou de classe?
Oui, nous pouvons utiliser des méthodes de synchronisation statiques. Selon les caractéristiques des méthodes statiques, il permet uniquement de l'appeler l'objet de classe et ne peut pas être appelé en instanciant un objet de classe. Ensuite, si vous obtenez le verrou de cette méthode statique, vous obtiendrez le verrouillage de la classe, et ce verrouillage de classe est tous les verrous de la classe TestThead, et le but d'obtenir les verrous de classe partagée est obtenu.
Le code d'implémentation est le suivant:
package thread_test; / ** * Tester des programmes multipliés qui étendent la mise en œuvre de la classe de threads * * @author Ciding * @createtime 7 décembre 2011 9:37:25 AM * * / Classe publique TestThread étend Thread {private int threadnum; public TestThread (int threadnum) {this.threadnum = threadnum; } public static synchronisé void strictest (int threadnum) {for (int i = 0; i <1000; i ++) {System.out.println ("non." + Threadnum + ":" + i); }} public static void main (String [] args) lève une exception {pour (int i = 0; i <10; i ++) {new TestThread (i) .Start (); Thread.Sleep (1); }} @Override public void run () {staticst (threadnum); }} Le résultat de l'exécution est omis, le même que dans le deuxième exemple.
Le contenu ci-dessus explique principalement deux problèmes: les blocs de synchronisation et les méthodes de synchronisation.
1. Bloc synchronisé: le verrouillage d'objet acquis est le verrouillage de l'objet de drapeau en synchronisé (drapeau).
2. Méthode de synchronisation: l'objet de classe auquel appartient la méthode et le verrouillage de l'objet de classe.
La méthode de synchronisation statique sera certainement synchronisée car plusieurs threads seront partagés.
Au lieu de méthodes de synchronisation statique, elles ne seront synchronisées qu'en mode singleton.