Cet article présente principalement les informations pertinentes sur la différence et la connexion entre volatile et synchronisé en Java. J'espère que cet article pourra aider tout le monde à comprendre cette partie du contenu. Les amis dans le besoin peuvent s'y référer
<.>La différence et le lien entre volatile et synchronisé en java
C'est peut-être le meilleur article comparant les effets de volatile et synchronisé. Volatile est un modificateur de variable et synchronisé est un modificateur de méthode ou de bloc. Nous utilisons donc ces deux mots-clés pour spécifier trois manières simples d'accéder aux variables
int i1; int geti1() {return i1;}
volatile int i2; int geti2() {return i2;}
int i3; synchronized int geti3() {return i3;}
Copier après la connexion
geti1() obtient la valeur immédiatement dans le fil de discussion actuel La valeur dans le variable i1. Un thread peut obtenir une copie locale d'une variable, et la valeur de la variable obtenue n'est pas nécessairement la même que la valeur obtenue par d'autres threads. En particulier, si d'autres threads modifient la valeur de i1, la valeur de i1 obtenue par le thread actuel peut être différente de la valeur modifiée. En fait, Java dispose d'un mécanisme de mémoire principale qui utilise une mémoire principale pour enregistrer la valeur correcte actuelle de la variable. Les threads copient les valeurs des variables dans leur propre mémoire indépendante, et les copies de mémoire de ces threads peuvent être différentes des valeurs de la mémoire principale. Ainsi, dans la pratique, il peut arriver que la valeur de i1 dans la mémoire principale soit 1, et que le thread 1 et le thread 2 aient modifié i1, mais que la valeur mise à jour n'ait pas été retransférée vers la mémoire principale ou d'autres threads. être dans le thread La valeur de i1 dans le thread 1 est 2, mais la valeur de i1 dans le thread 2 est 3.
D'un autre côté, geti2() peut effectivement obtenir la valeur de i2 à partir de la mémoire principale. Une variable volatile ne permet pas à un thread de copier la valeur de la variable de la mémoire principale vers son propre espace de stockage. Par conséquent, une variable déclarée volatile obtiendra les données de manière synchrone dans tous les threads. Peu importe que vous modifiiez la variable dans un thread, les autres threads obtiendront immédiatement le même résultat. Comme il est plus efficace pour les threads d'accéder ou de modifier leurs propres copies de données, les variables de type volatile consomment certaines performances.
Donc, si les variables volatiles peuvent déjà synchroniser les données entre les threads, à quoi servent les synchronisations ? Il y a deux différences entre les deux. Tout d'abord, synchronisé acquiert et libère les verrous contrôlés par l'écouteur. Si deux threads utilisent un écouteur (c'est-à-dire le même verrou d'objet), alors l'écouteur ne peut forcer qu'un seul thread à traiter le bloc de code à la fois. synchrone. De plus, synchronisé peut également synchroniser la mémoire. En pratique, synchronisé rend toute la mémoire des threads synchronisée avec la mémoire principale. Le processus d'exécution de geti3() est donc le suivant :
1. Le thread acquiert le verrou de l'objet auprès de l'écouteur. (Ici, on suppose que l'écouteur n'est pas verrouillé, sinon le thread ne peut pas obtenir le verrouillage de l'objet tant que l'écouteur n'est pas déverrouillé)
2 La mémoire du thread met à jour toutes les variables, ce qui signifie qu'il lira. les variables dans la mémoire principale Créez vos propres variables dont la validité est garantie. (La JVM utilisera un indicateur « sale » pour optimiser le processus afin que seules les variables avec l'indicateur « sale » soient mises à jour. Pour plus de détails, consultez 17.9 de la spécification JAVA)
3. Le bloc est exécuté (Dans cet exemple, définissez la valeur de retour sur la valeur actuelle de i3 qui vient d'être réinitialisée à partir de la mémoire principale.)
Toute modification apportée aux variables sera réécrite dans la mémoire principale. . Mais il n’y a aucun changement dans geti3() dans cet exemple.
5. Le fil libère le verrou de l'objet pour l'auditeur.
So volatile ne peut synchroniser la valeur d'une variable qu'entre la mémoire du thread et la mémoire principale, tandis que synchronisé synchronise la valeur de toutes les variables entre la mémoire du thread et la mémoire principale, et en verrouillant et relâchant l'écouteur pour obtenir ce. De toute évidence, la synchronisation coûtera plus cher en performances que la volatilité.
À propos de la différence entre les deux
1 Volatile indique essentiellement au jvm que la valeur de la variable actuelle dans le registre (mémoire de travail) est incertaine. . Il doit être lu à partir de la mémoire principale ; la synchronisation verrouille la variable actuelle. Seul le thread actuel peut accéder à la variable et les autres threads sont bloqués.
2.volatile ne peut être utilisé qu'au niveau de la variable ; synchronisé peut être utilisé aux niveaux de la variable, de la méthode et de la classe
3.
volatile peut être implémenté uniquement La visibilité des modifications des variables ne peut pas garantir l'atomicité; tandis que la synchronisation peut garantir la visibilité des modifications et l'atomicité des variables
4. Volatile ne provoquera pas de blocage de thread ;
5. Les variables marquées volatiles ne seront pas optimisées par le compilateur ; les variables marquées synchronisées peuvent être optimisées par le compilateur
Les raisons de la partie police rouge sont les suivants :
Lorsque le thread A modifie la variable avant qu'elle ne se termine, un autre thread B peut voir la valeur modifiée et peut modifier la variable sans attendre que A libère le verrou, car Volatile variables débloquées
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!