volatile
a une sémantique pour la visibilité de la mémoire. Fondamentalement, la valeur d'un volatile
champ devient visible pour tous les lecteurs (autres threads en particulier) après qu'une opération d'écriture y est terminée. Sans volatile
, les lecteurs pourraient voir une valeur non mise à jour.
Pour répondre à votre question: Oui, j'utilise une volatile
variable pour contrôler si du code continue une boucle. La boucle teste la volatile
valeur et continue si elle l'est true
. La condition peut être définie sur false
en appelant une méthode "stop". La boucle voit false
et se termine lorsqu'elle teste la valeur une fois la méthode d'arrêt terminée.
Le livre " Java Concurrency in Practice ", que je recommande vivement, donne une bonne explication volatile
. Ce livre est écrit par la même personne qui a écrit l'article IBM référencé dans la question (en fait, il cite son livre au bas de cet article). Mon utilisation volatile
est ce que son article appelle le «drapeau d'état du motif 1».
Si vous souhaitez en savoir plus sur le volatile
fonctionnement sous le capot, lisez le modèle de mémoire Java . Si vous voulez aller au-delà de ce niveau, consultez un bon livre d'architecture informatique comme Hennessy & Patterson et lisez sur la cohérence et la cohérence du cache.
volatile
celle fournie avec le nouveau modèle de mémoire Java défini dans JSR 133: que lorsqu'un thread lit unevolatile
variable, il voit non seulement la dernière valeur qui lui a été écrite par un autre thread, mais aussi toutes les autres écritures sur d'autres variables qui étaient visibles dans cet autre fil au moment de l'volatile
écriture. Voir cette réponse et cette référence .«… Le modificateur volatile garantit que tout thread qui lit un champ verra la dernière valeur écrite.» - Josh Bloch
Si vous songez à utiliser
volatile
, lisez le paquetjava.util.concurrent
qui traite du comportement atomique.Le post Wikipedia sur un modèle Singleton montre une utilisation volatile.
la source
volatile
et dessynchronized
mots clés?volatile
exemple. Il peut être trouvé dans une version archivée .void
-public
clés".Point important sur
volatile
:synchronized
etvolatile
et serrures.synchronized
variable. L'utilisation d'unsynchronized
mot clé avec une variable est illégale et entraînera une erreur de compilation. Au lieu d'utiliser lasynchronized
variable en Java, vous pouvez utiliser lavolatile
variable java , qui demandera aux threads JVM de lire la valeur de lavolatile
variable dans la mémoire principale et de ne pas la mettre en cache localement.volatile
mot clé.la source
Exemple d'utilisation de
volatile
:Nous créons une instance paresseusement au moment de la première demande.
Si nous ne faisons pas la
_instance
variable,volatile
le thread qui crée l'instance deSingleton
n'est pas en mesure de communiquer avec l'autre thread. Donc, si le thread A crée une instance Singleton et juste après sa création, le CPU corrompt, etc., tous les autres threads ne pourront pas voir la valeur de_instance
comme non nul et ils croiront qu'il est toujours attribué null.Pourquoi cela arrive-t-il? Étant donné que les threads de lecture ne font aucun verrouillage et tant que le thread d'écriture ne sort pas d'un bloc synchronisé, la mémoire ne sera pas synchronisée et la valeur de
_instance
ne sera pas mise à jour dans la mémoire principale. Avec le mot-clé Volatile en Java, cela est géré par Java lui-même et ces mises à jour seront visibles par tous les threads de lecture.Exemple d'utilisation de sans volatile:
Le code ci-dessus n'est pas thread-safe. Bien qu'il vérifie à nouveau la valeur de l'instance dans le bloc synchronisé (pour des raisons de performances), le compilateur JIT peut réorganiser le bytecode de manière à ce que la référence à l'instance soit définie avant que le constructeur ait terminé son exécution. Cela signifie que la méthode getInstance () renvoie un objet qui n'a peut-être pas été complètement initialisé. Pour rendre le code thread-safe, le mot-clé volatile peut être utilisé depuis Java 5 pour la variable d'instance. Les variables marquées comme volatiles ne sont visibles que pour les autres threads une fois que le constructeur de l'objet a complètement terminé son exécution.
La source
volatile
utilisation en Java :Les itérateurs à échec rapide sont généralement implémentés à l'aide d'un
volatile
compteur sur l'objet liste.Iterator
est créé, la valeur actuelle du compteur est incorporée dans l'Iterator
objet.Iterator
opération est effectuée, la méthode compare les deux valeurs de compteur et renvoie aConcurrentModificationException
si elles sont différentes.L'implémentation d'itérateurs à sécurité intégrée est généralement légère. Ils s'appuient généralement sur les propriétés des structures de données de l'implémentation de liste spécifique. Il n'y a pas de schéma général.
la source
private static final Singleton _instance;
.volatile
est très utile pour arrêter les threads.Non pas que vous deviez écrire vos propres threads, Java 1.6 a beaucoup de jolis pools de threads. Mais si vous êtes sûr d'avoir besoin d'un fil, vous devrez savoir comment l'arrêter.
Le modèle que j'utilise pour les threads est:
Dans le segment de code ci-dessus, la lecture du thread
close
dans la boucle while est différente de celle qui appelleclose()
. Sans volatile, le thread exécutant la boucle peut ne jamais voir le changement se fermer.Remarquez qu'il n'y a pas besoin de synchronisation
la source
volatile
mot - clé, et il semble toujours fonctionner correctement.Un exemple courant d'utilisation
volatile
consiste à utiliser unevolatile boolean
variable comme indicateur pour terminer un thread. Si vous avez démarré un thread et que vous souhaitez pouvoir l'interrompre en toute sécurité à partir d'un autre thread, vous pouvez demander au thread de vérifier périodiquement un indicateur. Pour l'arrêter, définissez le drapeau sur true. En créant l'indicateurvolatile
, vous pouvez vous assurer que le thread qui le vérifie verra qu'il a été défini la prochaine fois qu'il le vérifiera sans même avoir à utiliser unsynchronized
bloc.la source
Une variable déclarée avec un
volatile
mot-clé, a deux qualités principales qui la rendent spéciale.Si nous avons une variable volatile, elle ne peut pas être mise en cache dans la mémoire cache de l'ordinateur (microprocesseur) par aucun thread. L'accès a toujours eu lieu à partir de la mémoire principale.
S'il y a une opération d'écriture en cours sur une variable volatile et qu'une opération de lecture est soudainement demandée, il est garanti que l' opération d'écriture sera terminée avant l'opération de lecture .
Deux qualités ci-dessus en déduisent que
Et d'autre part,
volatile
mot - clé est un moyen idéal pour maintenir une variable partagée qui a 'n' nombre de threads de lecture et un seul thread d'écriture pour y accéder. Une fois levolatile
mot clé ajouté , c'est fait. Aucun autre frais généraux sur la sécurité des threads.Inversement,
Nous ne pouvons pas utiliser le
volatile
mot clé uniquement pour satisfaire une variable partagée qui a plus d'un thread d'écriture y accédant .la source
Personne n'a mentionné le traitement des opérations de lecture et d'écriture pour les types de variables longues et doubles. Les lectures et écritures sont des opérations atomiques pour les variables de référence et pour la plupart des variables primitives, à l'exception des types de variables longues et doubles, qui doivent utiliser le mot-clé volatile pour être des opérations atomiques. @lien
la source
Oui, volatile doit être utilisé chaque fois que vous souhaitez qu'une variable mutable soit accessible par plusieurs threads. Ce n'est pas un cas d'utilisation très courant, car vous devez généralement effectuer plus d'une seule opération atomique (par exemple, vérifier l'état de la variable avant de le modifier), auquel cas vous utiliseriez plutôt un bloc synchronisé.
la source
À mon avis, deux scénarios importants autres que l'arrêt du thread dans lequel un mot-clé volatil est utilisé sont:
la source
Vous devrez utiliser un mot clé «volatile» ou «synchronisé» et tout autre outil et technique de contrôle des accès concurrents que vous pourriez avoir à votre disposition si vous développez une application multithread. Un exemple d'une telle application est les applications de bureau.
Si vous développez une application qui serait déployée sur le serveur d'applications (Tomcat, JBoss AS, Glassfish, etc.), vous n'avez pas à gérer vous-même le contrôle d'accès simultané car il est déjà traité par le serveur d'applications. En fait, si je me souviens bien, la norme Java EE interdit tout contrôle de concurrence dans les servlets et les EJB, car il fait partie de la couche «infrastructure» dont vous êtes censé être libéré. Vous ne contrôlez la concurrence dans une telle application que si vous implémentez des objets singleton. Cela a déjà été résolu si vous tricotez vos composants en utilisant frameworkd comme Spring.
Ainsi, dans la plupart des cas de développement Java où l'application est une application Web et utilisant un framework IoC comme Spring ou EJB, vous n'auriez pas besoin d'utiliser 'volatile'.
la source
volatile
garantit uniquement que tous les threads, même eux-mêmes, sont incrémentés. Par exemple: un compteur voit la même face de la variable en même temps. Il n'est pas utilisé à la place de choses synchronisées ou atomiques ou autres, il synchronise complètement les lectures. Veuillez ne pas le comparer avec d'autres mots clés Java. Comme le montre l'exemple ci-dessous, les opérations de variables volatiles sont également atomiques, elles échouent ou réussissent à la fois.Même si vous mettez des résultats volatils ou non, les résultats seront toujours différents. Mais si vous utilisez AtomicInteger comme ci-dessous, les résultats seront toujours les mêmes. C'est la même chose avec synchronisé également.
la source
Oui, je l'utilise beaucoup - cela peut être très utile pour du code multi-thread. L'article que vous avez signalé est bon. Bien qu'il y ait deux choses importantes à garder à l'esprit:
la source
Chaque thread accédant à un champ volatile lira sa valeur actuelle avant de continuer, au lieu d'utiliser (potentiellement) une valeur mise en cache.
Seule la variable membre peut être volatile ou transitoire.
la source
Absolument oui. (Et pas seulement en Java, mais aussi en C #.) Il y a des moments où vous devez obtenir ou définir une valeur qui est garantie d'être une opération atomique sur votre plate-forme donnée, un int ou un booléen, par exemple, mais ne nécessite pas les frais généraux de verrouillage de fil. Le mot clé volatile vous permet de vous assurer que lorsque vous lisez la valeur, vous obtenez la valeur actuelle et non une valeur mise en cache qui vient d'être rendue obsolète par une écriture sur un autre thread.
la source
Il existe deux utilisations différentes du mot-clé volatile.
Un indicateur occupé est utilisé pour empêcher un thread de continuer pendant que le périphérique est occupé et que l'indicateur n'est pas protégé par un verrou:
Le thread de test continuera lorsqu'un autre thread désactivera le drapeau occupé :
Cependant, comme occupé est fréquemment consulté dans le thread de test, la JVM peut optimiser le test en plaçant la valeur de occupé dans un registre, puis tester le contenu du registre sans lire la valeur de occupé en mémoire avant chaque test. Le thread de test ne verrait jamais de changement d'occupation et l'autre thread ne changerait que la valeur d'occupation en mémoire, ce qui entraînerait un blocage. Déclarer l' indicateur occupé comme volatile force sa valeur à être lue avant chaque test.
L'utilisation de variables volatiles réduit le risque d' erreurs de cohérence de la mémoire , car toute écriture dans une variable volatile établit une relation "se produit avant" avec les lectures suivantes de cette même variable. Cela signifie que les modifications apportées à une variable volatile sont toujours visibles pour les autres threads.
La technique de lecture, d'écriture sans erreurs de cohérence de la mémoire est appelée action atomique .
Une action atomique est une action qui se produit efficacement en même temps. Une action atomique ne peut pas s'arrêter au milieu: soit elle se produit complètement, soit elle ne se produit pas du tout. Aucun effet secondaire d'une action atomique n'est visible tant que l'action n'est pas terminée.
Vous trouverez ci-dessous des actions atomiques que vous pouvez spécifier:
À votre santé!
la source
volatile
dit pour un programmeur que la valeur sera toujours à jour. Le problème est que la valeur peut être enregistrée sur différents types de mémoire matérielle. Par exemple, il peut s'agir de registres CPU, cache CPU, RAM ... Les registres CPU et le cache CPU appartiennent au CPU et ne peuvent pas partager de données contrairement à la RAM qui est à la rescousse dans un environnement multithreadingvolatile
Le mot clé indique qu'une variable sera lue et écrite directement depuis / vers la mémoire RAM . Il a une empreinte de calculJava 5
étenduvolatile
en soutenanthappens-before
[À propos]volatile
Le mot clé ne résout pas unerace condition
situation où plusieurs threads peuvent écrire simultanément certaines valeurs. La réponse est lesynchronized
mot clé [À propos]En conséquence , il sécurité que si un fil écrit et d' autres lisent juste la
volatile
valeurvolatile vs synchronisé
la source
Volatile suit.
1> La lecture et l'écriture des variables volatiles par différents threads se font toujours à partir de la mémoire, pas à partir du cache du thread ou du registre CPU. Ainsi, chaque thread traite toujours de la dernière valeur. 2> Lorsque 2 threads différents fonctionnent avec la même instance ou des variables statiques dans le tas, on peut voir les actions des autres comme non ordonnées. Voir le blog de Jeremy Manson à ce sujet. Mais volatile aide ici.
Le code suivant en cours d'exécution montre comment un certain nombre de threads peuvent s'exécuter dans un ordre prédéfini et imprimer des sorties sans utiliser de mot clé synchronisé.
Pour ce faire, nous pouvons utiliser le code de fonctionnement complet suivant.
Le lien github suivant a un readme, qui donne une explication appropriée. https://github.com/sankar4git/volatile_thread_ordering
la source
Depuis la page de documentation d'Oracle , le besoin de variable volatile se pose pour résoudre les problèmes de cohérence de la mémoire:
Cela signifie que les modifications apportées à une
volatile
variable sont toujours visibles pour les autres threads. Cela signifie également que lorsqu'un thread lit une variable volatile, il voit non seulement la dernière modification apportée à lavolatile
, mais également les effets secondaires du code qui a provoqué la modification.Comme expliqué en
Peter Parker
réponse, en l'absence devolatile
modificateur, la pile de chaque thread peut avoir sa propre copie de variable. En rendant la variable asvolatile
, les problèmes de cohérence de la mémoire ont été corrigés.Jetez un œil à la page du didacticiel jenkov pour une meilleure compréhension.
Jetez un coup d'œil à la question SE connexe pour plus de détails sur les cas volatils et les cas d'utilisation de volatils:
Différence entre volatile et synchronisé en Java
Un cas d'utilisation pratique:
Vous avez beaucoup de discussions, qui ont besoin d'imprimer l' heure dans un format particulier , par exemple:
java.text.SimpleDateFormat("HH-mm-ss")
. Yon peut avoir une classe, qui convertit l'heure actuelle enSimpleDateFormat
et met à jour la variable pour chaque seconde. Tous les autres threads peuvent simplement utiliser cette variable volatile pour imprimer l'heure actuelle dans les fichiers journaux.la source
Les variables volatiles sont une synchronisation légère. Lorsque la visibilité des données les plus récentes sur tous les threads est requise et que l'atomicité peut être compromise, dans de telles situations, les variables volatiles doivent être préférées. La lecture des variables volatiles renvoie toujours l'écriture la plus récente effectuée par n'importe quel thread car elles ne sont ni mises en cache dans les registres ni dans les caches où les autres processeurs ne peuvent pas voir. Volatile est sans verrou. J'utilise volatile, lorsque le scénario répond aux critères mentionnés ci-dessus.
la source
La clé volatile, lorsqu'elle est utilisée avec une variable, s'assurera que les threads lisant cette variable verront la même valeur. Maintenant, si vous avez plusieurs threads lisant et écrivant dans une variable, rendre la variable volatile ne sera pas suffisant et les données seront corrompues. Les threads d'image ont lu la même valeur mais chacun a effectué quelques changements (par exemple incrémenté un compteur), lors de la réécriture dans la mémoire, l'intégrité des données est violée. C'est pourquoi il est nécessaire de synchroniser les variables (différentes manières sont possibles)
Si les changements sont effectués par 1 thread et que les autres ont juste besoin de lire cette valeur, le volatile conviendra.
la source
La variable volatile est essentiellement utilisée pour la mise à jour instantanée (vidage) dans la ligne de cache partagée principale une fois mise à jour, de sorte que les modifications se reflètent immédiatement sur tous les threads de travail.
la source
Ci-dessous est un code très simple pour démontrer l'exigence de la
volatile
variable for qui est utilisée pour contrôler l'exécution du thread à partir d'un autre thread (c'est un scénario où celavolatile
est requis).Lorsque
volatile
n'est pas utilisé: vous ne verrez jamais le message « Arrêté sur: xxx » même après « Arrêt sur: xxx » et le programme continue de s'exécuter.Lorsqu'il est
volatile
utilisé: vous verrez immédiatement le message « Arrêté: xxx ».Démo: https://repl.it/repls/SilverAgonizingObjectcode
la source