Leitfaden für das volatile Keyword in Java

Anleitung zum flüchtigen Schlüsselwort in Java

1. Überblick

In diesem kurzen Artikel konzentrieren wir uns auf ein grundlegendes, aber häufig missverstandenes Konzept in der Java-Sprache - das Schlüsselwortvolatile.

In Java hat jeder Thread einen separaten Speicherbereich, der als Arbeitsspeicher bezeichnet wird. Dies enthält die Werte verschiedener Variablen, die zur Ausführung von Operationen verwendet werden. Nach dem Ausführen einer Operation kopiert der Thread den aktualisierten Wert der Variablen in den Hauptspeicher, und von dort können andere Threads den neuesten Wert lesen.

Einfach ausgedrückt markiert das Schlüsselwortvolatileeine Variable, die sowohl für Lese- als auch für Schreibvorgänge immer in den Hauptspeicher wechselt, wenn mehrere Threads darauf zugreifen.

2. Wann wirdvolatile verwendet?

In Situationen, in denen der nächste Wert der Variablen vom vorherigen Wert abhängt, besteht die Möglichkeit, dass mehrere Threads, die die Variable lesen und schreiben, aufgrund einer Zeitlücke zwischen dem Lesen und dem Zurückschreiben in den Hauptspeicher nicht mehr synchron sind .

Dies kann anhand eines einfachen Beispiels veranschaulicht werden:

public class SharedObject {
    private volatile int count = 0;

    public void increamentCount() {
        count++;
    }
    public int getCount() {
        return count;
    }
}

With no synchronization here, a typical race condition can occur. Grundsätzlich können andere Threads bei einer Ausführungslücke zwischen Inkrementieren und Schreiben in den Hauptspeicher den Wert 0 sehen und versuchen, ihn in den Hauptspeicher zu schreiben.

Die Racebedingung kann natürlich auch durch die Verwendung der von Java bereitgestellten atomaren Datentypen wieAtomicInt oderAtomicLong vermieden werden.

3. Flüchtige und Thread-Synchronisation

Für alle Multithread-Anwendungen müssen wir einige Regeln für ein konsistentes Verhalten festlegen:

  • Gegenseitiger Ausschluss - Nur ein Thread führt jeweils einen kritischen Abschnitt aus

  • Sichtbarkeit - Änderungen, die von einem Thread an den freigegebenen Daten vorgenommen wurden, sind für andere Threads sichtbar, um die Datenkonsistenz zu gewährleisten

Die Methoden und Blöcke vonSynchronizedbieten beide oben genannten Eigenschaften auf Kosten der Leistung der Anwendung.

Volatile ist ein ziemlich nützliches Grundelement, weil escan help ensure the visibility aspect of the data change, without, of course, providing the mutual exclusion ist. Daher ist es nützlich, wenn mehrere Threads einen Codeblock parallel ausführen, aber wir müssen die Sichtbarkeitseigenschaft sicherstellen.

4. Vorher-Garantie

Ab Java 5 bietet das Schlüsselwortvolatile zusätzliche Funktionen, mit denen sichergestellt wird, dass Werte aller Variablen, einschließlich nichtflüchtiger Variablen, zusammen mit der SchreiboperationVolatilein den Hauptspeicher geschrieben werden.

Dies wird als Happens-Before bezeichnet, da alle Variablen für einen anderen Lesethread sichtbar sind. Außerdem ordnet JVM die Lese- und Schreibanweisungen der Variablen vonvolatilenicht neu an.

Schauen wir uns das Beispiel an:

Thread 1
    object.aNonValitileVariable = 1;
    object.aVolatileVariable = 100; // volatile write

Thread 2:
    int aNonValitileVariable = object.aNonValitileVariable;
    int aVolatileVariable =  object.aVolatileVariable;

In diesem Fall wird, wennThread 1 den Wert vonaVolatileVariable geschrieben hat, auch der Wert vonaNonValitileVariable in den Hauptspeicher geschrieben. And even though it’s not a volatile variable, it is exhibiting a volatile behavior.

Durch Verwendung dieser Semantik können wir nur einige der Variablen in unserer Klasse alsvolatiledefinieren und die Sichtbarkeitsgarantie optimieren.

5. Fazit

In diesem Tutorial haben wir uns eingehender mit dem Schlüsselwortvolatileund seinen Funktionen sowie den Verbesserungen befasst, die ab Java 5 vorgenommen wurden.

Wie immer finden Sie die Codebeispieleover on GitHub.