Point important sur volatile:
- La synchronisation en Java est possible en utilisant des mots - clés Java
synchronizedet volatileet serrures.
- En Java, nous ne pouvons pas avoir de
synchronizedvariable. L'utilisation d'un synchronizedmot clé avec une variable est illégale et entraînera une erreur de compilation. Au lieu d'utiliser la synchronizedvariable en Java, vous pouvez utiliser la volatilevariable java , qui demandera aux threads JVM de lire la valeur de la volatilevariable dans la mémoire principale et de ne pas la mettre en cache localement.
- Si une variable n'est pas partagée entre plusieurs threads, il n'est pas nécessaire d'utiliser le
volatilemot clé.
la source
Exemple d'utilisation de volatile:
public class Singleton {
private static volatile Singleton _instance; // volatile variable
public static Singleton getInstance() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
Nous créons une instance paresseusement au moment de la première demande.
Si nous ne faisons pas la _instancevariable, volatilele thread qui crée l'instance de Singletonn'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 _instancecomme 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 _instancene 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.
Conclusion : le volatilemot-clé est également utilisé pour communiquer le contenu de la mémoire entre les threads.
Exemple d'utilisation de sans volatile:
public class Singleton{
private static Singleton _instance; //without volatile variable
public static Singleton getInstance(){
if(_instance == null){
synchronized(Singleton.class){
if(_instance == null) _instance = new Singleton();
}
}
return _instance;
}
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

volatileutilisation en Java :
Les itérateurs à échec rapide sont généralement implémentés à l'aide d'un volatilecompteur sur l'objet liste.
- Lorsque la liste est mise à jour, le compteur est incrémenté.
- Lorsqu'un
Iteratorest créé, la valeur actuelle du compteur est incorporée dans l' Iteratorobjet.
- Lorsqu'une
Iteratoropération est effectuée, la méthode compare les deux valeurs de compteur et renvoie a ConcurrentModificationExceptionsi 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.
volatilecelle fournie avec le nouveau modèle de mémoire Java défini dans JSR 133: que lorsqu'un thread lit unevolatilevariable, 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 .