Donc, je viens d'apprendre sur le mot-clé volatile tout en écrivant quelques exemples pour une section que je suis TA demain. J'ai écrit un programme rapide pour démontrer que les opérations ++ et - ne sont pas atomiques.Pourquoi le marquage d'une variable Java volatile rend les choses moins synchronisées?
public class Q3 {
private static int count = 0;
private static class Worker1 implements Runnable{
public void run(){
for(int i = 0; i < 10000; i++)
count++; //Inner class maintains an implicit reference to its parent
}
}
private static class Worker2 implements Runnable{
public void run(){
for(int i = 0; i < 10000; i++)
count--; //Inner class maintains an implicit reference to its parent
}
}
public static void main(String[] args) throws InterruptedException {
while(true){
Thread T1 = new Thread(new Worker1());
Thread T2 = new Thread(new Worker2());
T1.start();
T2.start();
T1.join();
T2.join();
System.out.println(count);
count = 0;
Thread.sleep(500);
}
}
}
Comme prévu la sortie de ce programme est généralement le long des lignes de:
-1521
-39
0
0
0
0
0
0
Cependant, quand je change:
private static int count = 0;
à
private static volatile int count = 0;
ma la sortie passe à:
0
3077
1
-3365
-1
-2
2144
3
0
-1
1
-2
6
1
1
J'ai lu When exactly do you use the volatile keyword in Java? donc je sens que j'ai une compréhension de base de ce que le mot-clé ne (maintenir la synchronisation à travers des copies mises en cache d'une variable dans différents threads, mais est en lecture update-écriture pas en sécurité) . Je comprends que ce code n'est, bien sûr, pas sécurisé. Il est spécifiquement non thread-safe d'agir comme un exemple pour mes étudiants. Cependant, je suis curieux de savoir pourquoi l'ajout du mot-clé volatile rend la sortie moins «stable» que lorsque le mot-clé n'est pas présent.
Merci pour cette réponse. En dépit de demander il y a trois ans c'est la meilleure explication que j'ai entendue. – JohnS
Ceci est complètement faux Thread.start et Thread.join créent des "barrières de mémoire". http://docs.oracle.com/javase/tutorial/essential/concurrency/memconsist.html voir ma réponse pour le bon. – Oleg
@Oleg: Les barrières de mémoire Thread start & finish n'auront aucun effet pendant une course parallèle. Alors que la JVM peut montrer à chaque thread la même valeur dans le 'count' non-volatile, elle n'a pas besoin de le faire et ne le fera généralement pas. Je peux bien croire qu'une JVM pourrait exécuter les deux threads en séquence plutôt qu'en parallèle, bien que vous ayez toujours deux valeurs différentes parmi les trois copies de 'count'. Une fois que vous vous êtes éloigné de ce que le langage Java demande réellement, les choses peuvent varier beaucoup en fonction de la machine, de ce qui est en cours d'exécution, de la date et de l'heure, et de la JVM. – RalphChapin