logo

Flüchtiges Schlüsselwort in Java

Das Schlüsselwort „Volatile“ wird verwendet, um den Wert einer Variablen durch verschiedene Threads zu ändern. Es wird auch verwendet, um Klassen threadsicher zu machen. Dies bedeutet, dass mehrere Threads problemlos gleichzeitig eine Methode und eine Instanz der Klassen verwenden können. Das Schlüsselwort volatile kann entweder mit primitiven Typen oder Objekten verwendet werden.

Das Schlüsselwort volatile speichert den Wert der Variablen nicht zwischen und liest die Variable immer aus dem Hauptspeicher. Das Schlüsselwort volatile kann nicht mit Klassen oder Methoden verwendet werden. Es wird jedoch mit Variablen verwendet. Es garantiert auch Sichtbarkeit und Ordnung. Es verhindert, dass der Compiler den Code neu anordnet.

Der Inhalt des jeweiligen Geräteregisters kann sich jederzeit ändern. Daher benötigen Sie das Schlüsselwort volatile, um sicherzustellen, dass solche Zugriffe nicht vom Compiler wegoptimiert werden.

Beispiel

 class Test { static int var=5; } 

Nehmen Sie im obigen Beispiel an, dass zwei Threads an derselben Klasse arbeiten. Beide Threads laufen auf unterschiedlichen Prozessoren, wobei jeder Thread seine lokale Kopie von var hat. Wenn ein Thread seinen Wert ändert, wird die Änderung nicht im ursprünglichen Thread im Hauptspeicher widergespiegelt. Dies führt zu Dateninkonsistenzen, da der andere Thread den geänderten Wert nicht kennt.

 class Test { static volatile int var =5; } 

Im obigen Beispiel sind statische Variablen Klassenmitglieder, die von allen Objekten gemeinsam genutzt werden. Es gibt nur eine Kopie im Hauptspeicher. Der Wert einer flüchtigen Variablen wird niemals im Cache gespeichert. Sämtliche Lese- und Schreibvorgänge erfolgen vom und zum Hauptspeicher.

Wann sollte man es verwenden?

  • Sie können eine flüchtige Variable verwenden, wenn Sie Long- und Double-Variablen automatisch lesen und schreiben möchten.
  • Es kann als alternative Möglichkeit zur Synchronisierung in Java verwendet werden.
  • Alle Leserthreads sehen nach Abschluss des Schreibvorgangs den aktualisierten Wert der flüchtigen Variablen. Wenn Sie das Schlüsselwort volatile nicht verwenden, sehen verschiedene Leserthreads möglicherweise unterschiedliche Werte.
  • Es wird verwendet, um den Compiler darüber zu informieren, dass mehrere Threads auf eine bestimmte Anweisung zugreifen. Es verhindert, dass der Compiler eine Neuordnung oder Optimierung durchführt.
  • Wenn Sie keine flüchtigen Variablen verwenden, kann der Compiler den Code neu anordnen und den Wert der flüchtigen Variablen frei in den Cache schreiben, anstatt ihn aus dem Hauptspeicher zu lesen.

Wichtige Punkte

  • Sie können das Schlüsselwort volatile mit Variablen verwenden. Die Verwendung des Schlüsselworts volatile mit Klassen und Methoden ist illegal.
  • Es garantiert, dass der Wert der flüchtigen Variablen immer aus dem Hauptspeicher und nicht aus dem lokalen Thread-Cache gelesen wird.
  • Wenn Sie die Variable als flüchtig deklariert haben, sind Lese- und Schreibvorgänge atomar
  • Dadurch wird das Risiko eines Speicherkonsistenzfehlers verringert.
  • Jeder Schreibvorgang in eine flüchtige Variable in Java stellt ein Ereignis vor der Beziehung mit aufeinanderfolgenden Lesevorgängen derselben Variablen her.
  • Die flüchtigen Variablen sind für andere Threads immer sichtbar.
  • Die flüchtige Variable, die eine Objektreferenz ist, kann null sein.
  • Wenn eine Variable nicht von mehreren Threads gemeinsam genutzt wird, müssen Sie das Schlüsselwort volatile nicht für diese Variable verwenden.

Unterschied zwischen Synchronisation und volatilem Schlüsselwort

Das flüchtige Schlüsselwort ist kein Ersatz für das synchronisierte Schlüsselwort, kann aber in bestimmten Fällen als Alternative verwendet werden. Es gibt folgende Unterschiede:

Flüchtiges Schlüsselwort Synchronisierungsschlüsselwort
Das Schlüsselwort „Volatile“ ist ein Feldmodifikator. Das synchronisierte Schlüsselwort ändert Codeblöcke und Methoden.
Im Falle einer Volatilität kann der Thread nicht zum Warten blockiert werden. Im Falle einer Synchronisierung können Threads zum Warten blockiert werden.
Es verbessert die Thread-Leistung. Synchronisierte Methoden verschlechtern die Thread-Leistung.
Es synchronisiert jeweils den Wert einer Variablen zwischen Thread-Speicher und Hauptspeicher. Es synchronisiert den Wert aller Variablen zwischen Thread-Speicher und Hauptspeicher.
Flüchtige Felder unterliegen nicht der Compileroptimierung. Synchronize unterliegt der Compileroptimierung.

Beispiel für ein flüchtiges Schlüsselwort

Im folgenden Beispiel haben wir eine Klasse definiert, die den Zählerwert erhöht. Die run()-Methode in VolatileThread.java ruft den aktualisierten und alten Wert ab, wenn der Thread mit der Ausführung beginnt. In der Hauptklasse definieren wir das Thread-Array.

VolatileData.java

 public class VolatileData { private volatile int counter = 0; public int getCounter() { return counter; } public void increaseCounter() { ++counter; //increases the value of counter by 1 } } 

VolatileThread.java

 VolatileThread.java public class VolatileThread extends Thread { private final VolatileData data; public VolatileThread(VolatileData data) { this.data = data; } @Override public void run() { int oldValue = data.getCounter(); System.out.println('[Thread ' + Thread.currentThread().getId() + ']: Old value = ' + oldValue); data.increaseCounter(); int newValue = data.getCounter(); System.out.println('[Thread ' + Thread.currentThread().getId() + ']: New value = ' + newValue); } } 

VolatileMain.java

 public class VolatileMain { private final static int noOfThreads = 2; public static void main(String[] args) throws InterruptedException { VolatileData volatileData = new VolatileData(); //object of VolatileData class Thread[] threads = new Thread[noOfThreads]; //creating Thread array for(int i = 0; i <noofthreads; ++i) threads[i]="new" volatilethread(volatiledata); for(int i="0;" < noofthreads; threads[i].start(); starts all reader threads threads[i].join(); wait for } pre> <p> <strong>Output:</strong> </p> <pre> [Thread 9]: Old value = 0 [Thread 9]: New value = 1 [Thread 10]: Old value = 1 [Thread 10]: New value = 2 </pre> <hr></noofthreads;>