Pour votre exemple: si pas déclaré volatiles de la JVM de serveur pourrait hisser keepRunning
variable en dehors de la boucle, car il n'est pas modifiée dans la boucle (en le transformant en une boucle infinie), mais le client JVM ne le serait pas. C'est pourquoi vous voyez des résultats différents.
Explication générale sur les variables suivantes:
Lorsqu'un champ est déclarée volatile
, le compilateur et l'exécution sont avisés que cette variable est partagée et que les opérations sur il ne devrait pas être réorganisée avec d'autres opérations de mémoire. Variables ne sont pas mis en cache dans les registres ou dans les caches où ils sont cachés provenant d'autres
processeurs, et une lecture d'une variable volatile renvoie toujours la plus récente écrire par n'importe quel thread.
La visibilité des effets de la volatilité des variables de prolonger au-delà de la valeur de la volatilité de la variable elle-même. Lorsque le thread d'Un écrit à un volatile variable et par la suite le fil B lit la même variable, les valeurs de toutes les variables qui étaient visibles à Un avant d'écrire à la volatilité des variables deviennent visibles à B après la lecture de la volatilité de la variable
L'utilisation la plus courante de la volatilité des variables est comme un accomplissement, de l'interruption ou de l'indicateur d'état:
volatile boolean flag;
while (!flag) {
// do something untill flag is true
}
Variables peuvent être utilisées pour d'autres types d'informations d'état, mais plus d'attention est requise lors de la tentative de cette. Par exemple, la sémantique de la volatilité ne sont pas assez fort pour faire de l'opération d'incrémentation (count++
) atomique, sauf si vous pouvez garantir que la variable est écrite qu'à partir d'un seul fil.
Le verrouillage peut garantir à la fois la visibilité et l'atomicité; variables ne peuvent garantir la visibilité.
Vous pouvez utiliser des variables volatiles que lorsque tous les critères suivants sont respectés:
- Écrit à la variable ne dépend pas de sa valeur actuelle, ou vous pouvez
s'assurer qu'un seul thread jamais les mises à jour de la valeur;
- La variable ne doit pas participer à des invariants avec d'autres variables d'état; et
- Le verrouillage n'est pas nécessaire pour toute autre raison, alors que la variable est en cours d'accès.
Débogage astuce: assurez-vous de toujours spécifier le serveur de la JVM commutateur de ligne de commande lors de l'appel de la JVM, même pour le développement et les tests. La JVM de serveur effectue plus de l'optimisation de la JVM client, tels que le levage des variables en dehors d'une boucle qui ne sont pas modifiés dans la boucle; code qui peut apparaître à travailler dans l'environnement de développement (client JVM) peuvent se casser dans l'environnement de déploiement
(JVM de serveur).
Ceci est un extrait de Java de la Simultanéité dans la Pratique, le meilleur livre que vous pouvez trouver sur ce sujet.