La déclaration d'une statique de la variable en Java, signifie qu'il n'y aura qu'un seul exemplaire, peu importe la façon dont beaucoup d'objets de la classe sont créés. La variable sera accessible même sans les Objets créés. Cependant, les threads peuvent avoir mis en cache localement des valeurs.
Lorsqu'une variable est volatile et non pas statique, il y a une variable pour chaque Objet. Ainsi, sur la surface, il semble qu'il n'y a pas de différence à partir d'une variable normale, mais totalement différente de la statique. Cependant, même avec les champs Objet, un thread peut mettre en cache la valeur d'une variable locale.
Cela signifie que si deux threads mise à jour d'une variable du même Objet simultanément et de la variable n'est pas déclarée volatile, il pourrait y avoir des cas dans lesquels l'un des thread en cache une ancienne valeur.
Même si vous avez accès à un statique de la valeur à travers plusieurs threads, chaque thread peut avoir sa copie locale mise en cache! Pour éviter cela, vous pouvez déclarer la variable comme statique volatile et cela va forcer le fil à lire à chaque fois que la valeur globale.
Toutefois, la volatilité n'est pas un substitut à une bonne synchronisation! Par exemple:
private static volatile int counter = 0;
private void concurrentMethodWrong() {
counter = counter + 5;
//do something
counter = counter - 5;
}
L'exécution de concurrentMethodWrong simultanément de nombreuses fois peut conduire à une valeur finale du compteur différent de zéro! Pour résoudre le problème, vous devez mettre en œuvre un verrou:
private static final Object counterLock = new Object();
private static volatile int counter = 0;
private void concurrentMethodRight() {
synchronized (counterLock) {
counter = counter + 5;
}
//do something
synchronized (counterLock) {
counter = counter - 5;
}
}
Ou utiliser l' AtomicInteger
classe.