Le mot-clé synchronisé représente que cette méthode est verrouillée. Il est équivalent à quel thread (tel que le thread A), lors de l'exécution de cette méthode, vous devez vérifier si d'autres threads B (ou C, D, etc.) utilisent cette méthode (ou d'autres méthodes de synchronisation de cette classe). Si c'est le cas, attendez le thread B (ou C, D) qui utilise la méthode synchronisée pour exécuter cette méthode avant d'exécuter cette méthode. Sinon, verrouillez l'appelant et exécutez-le directement. Il comprend deux usages: la méthode synchronisée et le bloc synchronisé.
Le mécanisme de synchronisation multi-threadd verrouille les ressources afin qu'en même temps, un seul thread puisse fonctionner et que la synchronisation soit utilisée pour résoudre les problèmes qui peuvent survenir lorsque plusieurs threads accèdent simultanément.
Le mécanisme de synchronisation peut être implémenté en utilisant le mot-clé synchronisé.
Lorsque le mot-clé synchronisé modifie une méthode, la méthode est appelée méthode de synchronisation.
Lorsque la méthode synchronisée est exécutée ou une exception se produit, le verrou est automatiquement libéré.
Ce qui suit est un exemple pour analyser l'utilisation de mots clés synchronisés.
1. utilisation indifférentielle des mots clés synchronisés
Exemple de programme 1
classe publique threadtest {public static void main (string [] args) {exemple example = new Example (); Thread t1 = new Thread1 (exemple); Thread T2 = nouveau Thread1 (exemple); t1.start (); t2.start (); }} Exemple de classe {public synchronisé void execute () {for (int i = 0; i <10; ++ i) {try {Thread.Sleep (500); } catch (InterruptedException e) {e.printStackTrace (); } System.out.println ("Hello:" + i); }}} classe Thread1 étend Thread {Exemple privé Exemple; public thread1 (exemple exemple) {this.example = exemple; } @Override public void run () {example.execute (); }} Que ce soit pour prétendre le mot-clé synchronisé dans la méthode EXECUTE (), les résultats d'exécution de cet exemple de programme seront très différents.
Si le mot clé synchronisé n'est pas ajouté, les deux threads exécutent la méthode EXECUTE () en même temps et la sortie est deux groupes de simultanément.
Si le mot-clé synchronisé est ajouté, un ensemble de 0 à 9 sera d'abord sorti, puis l'ensemble suivant sera sorti, indiquant que les deux threads sont exécutés en séquence.
2. Situation multi-lancement de méthodes multiples
Modifiez le programme et ajoutez une autre méthode Execute2 () à l'exemple de classe.
Ensuite, écrivez un thread Class Thread2. La méthode run () dans Thread2 exécute EXECUTE2 (). Les deux méthodes de la classe d'exemples sont modifiées par le mot-clé synchronisé.
Exemple de programme 2
classe publique threadtest {public static void main (string [] args) {exemple example = new Example (); Thread t1 = new Thread1 (exemple); Thread T2 = nouveau Thread2 (exemple); t1.start (); t2.start (); }} Exemple de classe {public synchronisé void execute () {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (InterruptedException e) {e.printStackTrace (); } System.out.println ("Hello:" + i); }} public synchronisé void execute2 () {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (InterruptedException e) {e.printStackTrace (); } System.out.println ("world:" + i); }}} classe Thread1 étend Thread {Exemple privé Exemple; public thread1 (exemple exemple) {this.example = exemple; } @Override public void run () {example.execute (); }} classe Thread2 étend Thread {Exemple privé Exemple; public thread2 (exemple exemple) {this.example = exemple; } @Override public void run () {example.execcute2 (); }} Si le mot-clé synchronisé est supprimé, les deux méthodes sont exécutées simultanément et n'ont aucune influence mutuelle.
Mais comme écrit dans l'exemple de sous-programme, même deux méthodes:
Le résultat d'exécution est toujours la sortie d'un thread puis l'exécution d'un autre thread.
illustrer:
Si un objet a plusieurs méthodes synchronisées et qu'un thread a entré une méthode synchronisée à un certain moment, alors d'autres threads ne peuvent accéder à aucune méthode synchronisée de l'objet avant l'exécution de la méthode.
en conclusion:
Lorsque le mot-clé synchronisé modifie une méthode, la méthode est appelée méthode de synchronisation.
Chaque objet en Java a une serrure ou un moniteur. Lorsqu'un thread accède à la méthode synchronisée d'un objet, l'objet est verrouillé, et aucun autre thread ne peut accéder à la méthode synchronisée de l'objet (se réfère ici à toutes les méthodes de synchronisation, pas seulement la même méthode). Ce n'est que lorsque le thread précédent termine la méthode d'exécution (ou lance une exception), le verrouillage de l'objet est libéré, de sorte que d'autres threads peuvent accéder à nouveau à la méthode synchronisée de l'objet.
Notez que l'objet est verrouillé à ce moment. S'il s'agit d'un objet différent, il n'y a pas de relation de restriction entre les objets.
Lorsque vous essayez de construire un deuxième objet de thread dans le code, un nouvel exemple d'objet est passé, alors il n'y a pas de restriction entre l'exécution des deux threads.
3. Considérons les méthodes de synchronisation statique
Lorsqu'une méthode modifiée par mot-clé synchronisé est également modifiée par statique, il a été dit auparavant qu'une méthode de synchronisation non statique verra l'objet, mais la méthode statique n'appartient pas à l'objet, mais une classe, et elle verrouillera l'objet de classe de la classe où cette méthode est située.
Peu importe le nombre d'objets qu'une classe génère, ils correspondent au même objet de classe.
Exemple de programme 3
classe publique threadtest {public static void main (string [] args) {exemple example = new Example (); Thread t1 = new Thread1 (exemple); // Même si différents objets sont passés ici, la synchronisation de la méthode statique ne permet toujours pas à plusieurs threads de s'exécuter en même temps. Exemple = nouveau exemple (); Thread T2 = nouveau Thread2 (exemple); t1.start (); t2.start (); }} Exemple de classe {public synchronisé statique void execute () {for (int i = 0; i <20; ++ i) {try {Thread.Sleep ((long) math.random () * 1000); } catch (InterruptedException e) {e.printStackTrace (); } System.out.println ("Hello:" + i); }} public synchronisé statique void execute2 () {for (int i = 0; i <20; ++ i) {try {Thread.Sleep ((long) math.random () * 1000); } catch (InterruptedException e) {e.printStackTrace (); } System.out.println ("world:" + i); }}} classe Thread1 étend Thread {Exemple privé Exemple; public thread1 (exemple exemple) {this.example = exemple; } @Override public void run () {example.execute (); }} classe Thread2 étend Thread {Exemple privé Exemple; public thread2 (exemple exemple) {this.example = exemple; } @Override public void run () {example.execcute2 (); }} Donc, s'il s'agit d'une méthode statique (exécuter () et exécuter2 () ont toutes deux des mots clés statiques ajoutés), même si différents exemples d'objets sont transmis à deux threads, les deux threads sont toujours limités l'un de l'autre. Il faut d'abord être exécuté puis le suivant.
en conclusion:
Si une méthode synchronisée est statique, lorsqu'un thread accède à la méthode, il ne verrouille pas l'objet où se trouve la méthode synchronisée, mais l'objet de classe correspondant à la classe où se trouve la méthode synchronisée. En Java, peu importe le nombre d'objets d'une classe, ces objets correspondent à un objet de classe unique. Par conséquent, lorsqu'un thread accède à deux méthodes statiques et synchronisées de deux objets de la même classe, leur ordre d'exécution est également séquentiel, c'est-à-dire qu'un thread exécute d'abord la méthode et l'autre thread commence une fois l'exécution terminée.
4. Bloc synchronisé
Méthode d'écriture de blocage synchronisée:
synchronisé (objet) {} Cela signifie que le fil verra l'objet objet lors de sa réalisation. (Notez que cet objet peut être un objet de n'importe quelle classe, ou vous pouvez utiliser ce mot-clé).
De cette façon, vous pouvez spécifier vous-même l'objet verrouillé.
Exemple de programme 4
classe publique threadtest {public static void main (string [] args) {exemple example = new Example (); Thread t1 = new Thread1 (exemple); Thread T2 = nouveau Thread2 (exemple); t1.start (); t2.start (); }} Exemple de classe {objet privé objet = nouveau objet (); public void execute () {synchronisé (objet) {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (InterruptedException e) {e.printStackTrace (); } System.out.println ("Hello:" + i); }}} public void execute2 () {synchronisé (objet) {for (int i = 0; i <20; ++ i) {try {thread.sleep ((long) math.random () * 1000); } catch (InterruptedException e) {e.printStackTrace (); } System.out.println ("world:" + i); }}}}} classe Thread1 étend Thread {Exemple privé Exemple; public thread1 (exemple exemple) {this.example = exemple; } @Override public void run () {example.execute (); }} classe Thread2 étend Thread {Exemple privé Exemple; public thread2 (exemple exemple) {this.example = exemple; } @Override public void run () {example.execcute2 (); }} L'effet obtenu par l'exemple du programme 4 est le même que celui de l'exemple de programme 2. Les deux threads sont exécutés en séquence, plutôt que simultanément. Lorsqu'un thread s'exécute, l'objet objet est verrouillé et l'autre thread ne peut pas exécuter le bloc correspondant.
La méthode synchronisée est en fait équivalente à l'emballage de toutes les instructions dans la méthode avec un bloc synchronisé, puis en passant ce mot-clé dans les supports du bloc synchronisé. Bien sûr, s'il s'agit d'une méthode statique, l'objet de classe doit être verrouillé.
Peut-être que seulement quelques lignes de code dans une méthode impliqueront des problèmes de synchronisation des threads, de sorte que le bloc synchronisé contrôle l'accès de plusieurs threads plus granulaire que la méthode synchronisée. Seul le contenu du bloc synchronisé ne peut pas être accessible par plusieurs threads en même temps, et d'autres instructions dans la méthode sont toujours accessibles par plusieurs threads en même temps (y compris avant et après le bloc synchronisé).
Remarque: Les données protégées par synchronisées doivent être privées.
en conclusion:
La méthode synchronisée est un contrôle simultané à grain grossier. À un certain moment, un seul thread peut exécuter la méthode synchronisée;
Le bloc synchronisé est un contrôle de concurrence à grain fin, qui synchronise uniquement le code dans le bloc. D'autres codes situés dans la méthode et autres que les blocs synchronisés peuvent être accessibles par plusieurs threads en même temps.