Die Antwort von Kerem Baydogan ist vollkommen richtig. Ich möchte nur ein praktisches Beispiel dafür geben, was das volatile
Schlüsselwort uns bietet.
Zuerst haben wir einen Zähler, so etwas wie
public class Counter {
private int x;
public int getX() { return x; }
public void increment() { x++; }
}
Und einige Runnable-Aufgaben, die den Wert von x inkrementieren
@Override
public void run() {
for (N) {
int alterWert = counter.getX();
counter.increment();
int neuer Wert = counter.getX();
}
}
}
Ohne Synchronisierung kommt es zu Interferenzen zwischen Threads und es funktioniert einfach nicht.
Der einfachste Weg, dies zu lösen:
public class Counter {
private int x;
public synchronized int getX() { return x; }
public synchronized void increment() { x++; }
}
Um das System tatsächlich zum Absturz zu bringen, führe ich ein Thread.sleep
vor dem Lesen und Schreiben von x
Also, wofür ist volatile
nützlich? Es gibt viele gute Artikel darüber: volatile-Artikel oder diese Frage
Die Synchronisierung des Zugriffs auf die gemeinsame Ressource ist nicht die Antwort, aber es ist eine gute Wahl, um den Flag zum Stoppen von Threads zu halten
In unserem vorherigen Beispiel, stellen wir uns vor, wir möchten die Variable bis 100 inkrementieren, eine einfache Möglichkeit könnte ein volatile boolean
Flag sein. Beispiel:
private volatile boolean stop;
@Override
public void run() {
while(!stop) {
int alterWert = counter.getX();
if (alterWert == 100) {
stop = true;
} else {
counter.increment();
int neuer Wert = counter.getX();
}
}
}
Das funktioniert gut, aber wenn du das volatile
Schlüsselwort aus dem Flag entfernst, besteht die Möglichkeit einer Endlosschleife.
0 Stimmen
Um meinen automatischen "Möglicherweise" -Duplikatkommentar zu klären: Die beiden vorherigen Vorschläge waren keine exakten Duplikate; meiner ist es. Es ist wichtig, dass diese Frage als Duplikat geklärt wird, da die ausgewählte Antwort auf diese Frage gefährlich falsch ist, wenn sie behauptet, dass volatil nur das als volatil deklarierte Feld betrifft - tatsächlich führt ein Schreib- und ein Lesebefehl von jeder volatilen Variable eine vollständige Speicherbarriere ein, genauso wie die Synchronisation zwischen zwei Threads.