Wichtiger Punkt zu volatile
:
- Synchronisation in Java ist möglich durch die Verwendung von Java Schlüsselwort
synchronized
und volatile
und Schlösser.
- In Java können wir keine
synchronized
Variablen haben. Die Verwendung eines synchronized
Schlüsselworts mit einer Variablen ist unzulässig und führt zu einem Kompilierungsfehler. Anstatt die synchronized
Variable in Java zu verwenden, können Sie auch die Java- volatile
Variable verwenden, die JVM-Threads anweist, den Wert der volatile
Variablen aus dem Hauptspeicher zu lesen und nicht lokal zwischenzuspeichern.
- Wenn eine Variable nicht von mehreren Threads gemeinsam genutzt wird, muss das
volatile
Schlüsselwort nicht verwendet werden.
Quelle
Beispiel für die Verwendung von 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;
}
}
Wir erstellen die Instanz träge zum Zeitpunkt der ersten Anfrage.
Wenn wir die _instance
Variable nicht volatile
erstellen, kann der Thread, der die Instanz von erstellt, Singleton
nicht mit dem anderen Thread kommunizieren. Wenn Thread A eine Singleton-Instanz erstellt und die CPU unmittelbar nach der Erstellung beschädigt wird, können alle anderen Threads den Wert von _instance
nicht als null anzeigen und glauben, dass ihm immer noch null zugewiesen ist.
Warum passiert das? Da Reader-Threads nicht gesperrt werden und der Writer-Thread erst aus einem synchronisierten Block herauskommt, wird der Speicher nicht synchronisiert und der Wert von _instance
wird im Hauptspeicher nicht aktualisiert. Mit dem Schlüsselwort Volatile in Java wird dies von Java selbst behandelt, und solche Aktualisierungen sind für alle Reader-Threads sichtbar.
Schlussfolgerung : Das volatile
Schlüsselwort wird auch verwendet, um den Speicherinhalt zwischen Threads zu kommunizieren.
Beispiel Verwendung von ohne flüchtig:
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;
}
Der obige Code ist nicht threadsicher. Obwohl der Wert der Instanz innerhalb des synchronisierten Blocks (aus Leistungsgründen) erneut überprüft wird, kann der JIT-Compiler den Bytecode so neu anordnen, dass der Verweis auf die Instanz festgelegt wird, bevor der Konstruktor seine Ausführung beendet hat. Dies bedeutet, dass die Methode getInstance () ein Objekt zurückgibt, das möglicherweise nicht vollständig initialisiert wurde. Um den Code threadsicher zu machen, kann das Schlüsselwort volatile seit Java 5 für die Instanzvariable verwendet werden. Variablen, die als flüchtig markiert sind, werden für andere Threads erst sichtbar, wenn der Konstruktor des Objekts seine Ausführung vollständig abgeschlossen hat.
Quelle
volatile
Verwendung in Java :
Die ausfallsicheren Iteratoren werden normalerweise mithilfe eines volatile
Zählers für das Listenobjekt implementiert .
- Wenn die Liste aktualisiert wird, wird der Zähler erhöht.
- Wenn ein
Iterator
erstellt wird, wird der aktuelle Wert des Zählers in das Iterator
Objekt eingebettet .
- Wenn eine
Iterator
Operation ausgeführt wird, vergleicht die Methode die beiden Zählerwerte und löst a aus, ConcurrentModificationException
wenn sie unterschiedlich sind.
Die Implementierung von ausfallsicheren Iteratoren ist normalerweise leicht. Sie stützen sich normalerweise auf Eigenschaften der Datenstrukturen der spezifischen Listenimplementierung. Es gibt kein allgemeines Muster.
volatile
, die mit dem in JSR 133 definierten neuen Java-Speichermodell verbunden ist, wird weggelassen: Wenn ein Thread einevolatile
Variable liest , sieht er nicht nur den Wert, der zuletzt von einem anderen Thread in ihn geschrieben wurde, sondern auch alle anderen Schreibvorgänge in andere Variablen, die waren zum Zeitpunkt desvolatile
Schreibens in diesem anderen Thread sichtbar . Siehe diese Antwort und diese Referenz .