Maison  >  Article  >  Java  >  Une brève introduction aux mots-clés multithread Java volatile, lock et synchronisé

Une brève introduction aux mots-clés multithread Java volatile, lock et synchronisé

不言
不言original
2018-09-25 15:36:101928parcourir

Cet article vous apporte une brève introduction aux mots-clés multi-thread Java volatile, lock et synchronisé. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il vous sera utile. .

1. Volatile

Sémantique de la mémoire de l'écriture volatile et de la lecture volatile :

Le thread A écrit une variable volatile, qui est essentiellement le thread A écrivant dans la mémoire qui sera lu ensuite. Un thread de cette variable volatile a émis un message (qui a modifié la variable partagée). Lorsque le thread B lit une variable volatile, en substance, le thread B reçoit un message envoyé par un thread précédent (modifications de la variable partagée avant d'écrire la variable volatile). Le thread A écrit une variable volatile, puis le thread B lit la variable volatile. Ce processus est essentiellement le thread A qui envoie un message au thread B via la mémoire principale.

Sémantique de la mémoire de libération et d'acquisition du verrou :

Le thread A libère un verrou En substance, le thread A envoie un message à un thread qui acquerra ensuite le verrou (le thread A a un verrou partagé). Message de modification de variable). Le thread B acquiert un verrou. Essentiellement, le thread B reçoit un message envoyé par un thread précédent (modifications des variables partagées avant de libérer le verrou). Le thread A libère le verrou, puis le thread B acquiert le verrou. Ce processus consiste essentiellement pour le thread A à envoyer un message au thread B via la mémoire principale.

Résumé : le rôle du mot-clé volatile est de rendre les variables visibles (visibles) sur plusieurs threads, mais volatile à lui seul ne peut pas garantir la sécurité des threads. Le mot-clé volatile n'a pas le mot-clé synchronisé.

2. lock

Lock est une interface :

public interface Lock {  
   void lock();     
   void lockInterruptibly() throws InterruptedException;
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    void unlock();
    Condition newCondition();
}

lock(), tryLock(), tryLock(long time, TimeUnit unit) et lockInterruptably() sont Utilisé pour acquérir des serrures.

La méthode unLock() est utilisée pour libérer le verrou. La méthode tryLock() a une valeur de retour, ce qui signifie qu'elle est utilisée pour tenter d'acquérir le verrou. Si l'acquisition réussit, elle renvoie vrai. Si l'acquisition échoue (c'est-à-dire que le verrou a été acquis par un autre thread), il renvoie false, ce qui signifie que cette méthode reviendra quoi qu'il arrive immédiatement. Vous n'attendrez pas là-bas si vous ne parvenez pas à obtenir la serrure. La méthode tryLock (long time, TimeUnit unit) est similaire à la méthode tryLock (), mais la différence est que cette méthode attendra un certain temps pendant laquelle elle ne pourra pas obtenir le verrou si elle ne peut pas obtenir le verrou dans le délai imparti. limite, il retournera false. Renvoie vrai si le verrou a été obtenu initialement ou pendant la période d'attente. La méthode lockInterruptably() est spéciale. Lors de l'acquisition d'un verrou via cette méthode, si le thread attend d'acquérir le verrou, le thread peut répondre à l'interruption, c'est-à-dire interrompre l'état d'attente du thread. C'est-à-dire que lorsque deux threads veulent acquérir un verrou via lock.lockInterruptably() en même temps, si le thread A acquiert le verrou à ce moment-là et que le thread B attend seulement, alors la méthode threadB.interrupt() est appelé sur le thread B. Peut interrompre le processus d'attente du thread B.

Le verrouillage peut être interrompu pendant le processus d'acquisition du verrouillage. lock peut essayer d'acquérir le verrou si le verrou est détenu par un autre thread, il renvoie false et ne met pas le thread actuel en veille. Lorsque le verrou tente d'acquérir le verrou, il transmet un paramètre de temps. Si le verrou n'est pas acquis dans cet intervalle de temps, la demande est terminée. synchronisé libérera automatiquement le verrou, mais le verrouillage ne libérera pas automatiquement le verrou. Remarque : lock() peut être utilisé pour verrouiller un morceau de code, de sorte qu'un autre code doit attendre avant que le verrou ne soit libéré. ​​Il convient de noter que le verrou ne libérera pas automatiquement le verrou comme c'est le cas avec une synchronisation, il doit donc être placé dans un fichier. try-finally block , en vous assurant que le verrou est libéré.

Lock et synchronisé présentent les différences suivantes :

1) Lock est une interface, tandis que synchronisé est un mot-clé en Java, et synchronisé est une implémentation de langage intégrée

2) Lorsqu'une exception se produit, synchronisé libérera automatiquement le verrou occupé par le thread, donc cela ne provoquera pas de blocage, tandis que lorsqu'une exception se produit, si Lock ne libère pas activement le verrou via unLock(), il est probable qu'il le soit. provoquer un blocage. , donc lorsque vous utilisez Lock, vous devez libérer le verrou dans le bloc final

3) Lock peut permettre au thread en attente du verrou de répondre à l'interruption, mais synchronisé ne peut pas le faire. synchronisé, le thread en attente attendra indéfiniment et ne pourra pas répondre à l'interruption ;

4) Grâce au verrouillage, vous pouvez savoir si le verrou a été acquis avec succès, mais synchronisé ne peut pas le faire.

5) Le verrouillage peut améliorer l'efficacité des opérations de lecture de plusieurs threads. En termes de performances, si la concurrence pour les ressources n'est pas féroce, les performances des deux sont presque les mêmes. Lorsque la concurrence pour les ressources est très féroce (c'est-à-dire qu'il y a un grand nombre de threads en concurrence en même temps), les performances de Lock sont bien meilleures que celles de synchronisé. Par conséquent, il doit être sélectionné en fonction de la situation appropriée lors de son utilisation. ReentrantLock signifie « verrouillage réentrant ». Le concept de verrouillage réentrant est décrit dans la section suivante. ReentrantLock est la seule classe qui implémente l'interface Lock et ReentrantLock fournit plus de méthodes.

3. synchronisé

1. Lorsque deux threads simultanés accèdent au bloc de code de synchronisation synchronisé (ce) dans le même objet, un seul thread peut être exécuté à la fois. Un autre thread doit attendre que le thread actuel ait fini d'exécuter ce bloc de code avant de pouvoir exécuter ce bloc de code.

2. Cependant, lorsqu'un thread accède à un bloc de code synchronisé (this) d'un objet, un autre thread peut toujours accéder au bloc de code synchronisé non synchronisé (this) dans l'objet.

3. Ce qui est particulièrement important est que lorsqu'un thread accède à un bloc de code synchronisé (ceci) d'un objet, les autres threads ne pourront pas accéder à tous les autres blocs de code synchronisés (ceci) de l'objet.

4. Le troisième exemple est également applicable à d'autres blocs de codes de synchronisation. C'est-à-dire que lorsqu'un thread accède à un bloc de code synchronisé d'un objet, il obtient le verrou d'objet de cet objet. En conséquence, l'accès des autres threads à toutes les parties de code synchronisées de l'objet objet est temporairement bloqué. Portée du mot-clé synchronisé : au sein d'une instance d'objet, synchronisé aMethod(){} peut empêcher plusieurs threads d'accéder à la méthode synchronisée de cet objet en même temps (si un objet a plusieurs méthodes synchronisées, à condition qu'un thread accède à l'une des la méthode des méthodes synchronisées, les autres threads ne peuvent accéder simultanément à aucune méthode synchronisée dans cet objet). À l’heure actuelle, les méthodes synchronisées des différentes instances d’objet n’interfèrent pas les unes avec les autres. En d'autres termes, d'autres threads peuvent toujours accéder à la méthode synchronisée dans une autre instance d'objet de la même classe en même temps ; dans la portée d'une certaine classe, la méthode statique synchronisée aStaticMethod{} empêche plusieurs threads d'accéder à la méthode statique synchronisée dans cette classe. en même temps. Cela fonctionne sur toutes les instances d'objet de la classe.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn