Heim > Java > JavaBase > Was ist der Unterschied zwischen Volatilität und Synchronisierung?

Was ist der Unterschied zwischen Volatilität und Synchronisierung?

青灯夜游
Freigeben: 2020-11-19 14:42:33
Original
5449 Leute haben es durchsucht

Unterschiede: 1. Volatil verursacht keine Thread-Blockierung; synchronisiert kann eine Thread-Blockierung verursachen. 2. Volatile garantiert die Sichtbarkeit der Daten, kann jedoch nicht die Atomizität garantieren, während die Synchronisierung die Atomizität und indirekt die Sichtbarkeit garantieren kann. Sichtbarkeit: Nachdem ein Thread eine gemeinsam genutzte Variable geändert hat, können andere Threads die Änderung (Änderung) der Variablen sofort sehen (wahrnehmen).

Das Java-Speichermodell erreicht Sichtbarkeit, indem es die geänderten Werte von Variablen im Arbeitsspeicher mit dem Hauptspeicher synchronisiert und die neuesten Werte aus dem Hauptspeicher im Arbeitsspeicher aktualisiert, bevor die Variablen gelesen werden Hauptspeicher, um Sichtbarkeit zu erreichen.

Was ist der Unterschied zwischen Volatilität und Synchronisierung?

Atomizität Atomizität:

Eine Operation kann nicht unterbrochen werden, entweder sind alle Ausführungen abgeschlossen oder werden nicht ausgeführt.

Das Java-Speichermodell garantiert, dass alle Vorgänge innerhalb desselben Threads von oben nach unten erfolgen. Wenn jedoch mehrere Threads parallel ausgeführt werden, kann die Ordnungsmäßigkeit ihrer Vorgänge nicht garantiert werden.

OrdnungOrdnung:

In diesem Thread beobachtet, sind alle Vorgänge geordnet; wenn sie in einem anderen Thread in einem Thread beobachtet werden, sind alle Vorgänge ungeordnet.

Das Java-Speichermodell garantiert, dass alle Vorgänge innerhalb desselben Threads von oben nach unten erfolgen. Wenn jedoch mehrere Threads parallel ausgeführt werden, kann die Ordnungsmäßigkeit ihrer Vorgänge nicht garantiert werden.
Wenn ein Computer ein Programm ausführt, ordnen der Compiler und der Prozessor häufig die

Anweisungen

neu an, um die Leistung zu verbessern. Diese werden im Allgemeinen in die folgenden drei Typen unterteilt: In einer Single-Thread-Umgebung ist das endgültige Ausführungsergebnis des Programm und das Ergebnis der Codeausführung sind konsistent. Der Prozessor muss die

Datenabhängigkeiten zwischen Anweisungen bei der Neuordnung berücksichtigen.

In einer Multithread-Umgebung werden Threads abwechselnd ausgeführt. Aufgrund der Existenz einer Compiler-Optimierung können die Variablen neu angeordnet werden Wird die Verwendung in den beiden Threads garantiert? Es ist unmöglich festzustellen, ob die Variablen konsistent sind, und die Ergebnisse können nicht vorhergesagt werden. Tun Sie zuerst, was Sie in der Prüfung tun können, und tun Sie später, was Sie nicht können.

public void mySort(){
int x = 11; //1
int y = 12; //2
x= x+5; // 3
y = x*x;//4
Nach dem Login kopieren

Die mögliche Reihenfolge ist 1234 2134 1324, es ist unmöglich, dass Attribut 4 vor 1 und 3 liegt,
da eine Datenabhängigkeit besteht.
Was ist der Unterschied zwischen Volatilität und Synchronisierung?
volatile verbietet die Neuordnung von Anweisungen.

public class ReSortSeqDemo {
    int a = 0;
    boolean flag = false;
    
    public void method01() {
        a = 1;           // flag = true;
                         // ----线程切换----
        flag = true;     // a = 1;
    }

    public void method02() {
        if (flag) {
            a = a + 3;
            System.out.println("a = " + a);
        }
    }

}
Nach dem Login kopieren
Wenn zwei Threads gleichzeitig ausgeführt werden, werden Methode01 und Methode02 neu angeordnet. Wenn Thread 1 Methode01 ausführt und dann der umgeschaltete Thread 2 Methode02 ausführt, werden unterschiedliche Ergebnisse angezeigt.

Anweisungssortierung deaktivieren

volatile realisiert die Optimierung des Verbots der Neuordnung von Anweisungen und vermeidet so das Phänomen der Programmstörung in einer Multithread-Umgebung.

Was ist der Unterschied zwischen Volatilität und Synchronisierung?Verstehen Sie zunächst ein Konzept, Memory Barrier (Memory Barrier), auch bekannt als Speicherbarriere ist eine CPU-Anweisung mit zwei Funktionen:

Garantieren Sie die Ausführungsreihenfolge bestimmter Operationen.

Stellen Sie die Speichersichtbarkeit bestimmter Variablen sicher (verwenden Sie diese Funktion, um die Sichtbarkeit des flüchtigen Speichers zu erreichen).

Da der Compiler eine Optimierung der Befehlsneuordnung durchführen kann Wenn zwischen Anweisungen eine Speicherbarriere eingefügt wird, teilt dies dem Compiler und der CPU mit, dass durch diese Speicherbarriere-Anweisung keine Anweisungen neu angeordnet werden können. Mit anderen Worten: Durch das Einfügen einer Speicherbarriere ist es verboten, eine Neuordnung vor und nach der Speicherbarriere durchzuführen. Sortieroptimierung. Eine weitere Funktion der Speicherbarriere besteht darin, das Leeren verschiedener CPU-Cache-Daten zu erzwingen, sodass jeder Thread auf der CPU die neueste Version dieser Daten lesen kann.

Das Folgende ist ein schematisches Diagramm der Befehlssequenz, die generiert wird, nachdem flüchtiges Schreiben eine Speicherbarriere unter der konservativen Strategie eingefügt hat: Das Folgende ist ein schematisches Diagramm der Befehlssequenz, die generiert wird, nachdem flüchtiges Lesen eine Speicherbarriere unter der konservativen Strategie eingefügt hat :

Thread-Sicherheit Sichtbarkeitsgarantie

Synchronisationsverzögerung zwischen Arbeitsspeicher und Hauptspeicher führt zu Sichtbarkeitsproblemen
Kann mit synchronisierten oder flüchtigen Schlüsselwörtern gelöst werden, sie können Variablen verwenden, die von einem Thread geändert wurden, um für andere sofort sichtbar zu sein Threads Was ist der Unterschied zwischen Volatilität und Synchronisierung? Durch die Neuanordnung von Anweisungen verursachte Sichtbarkeitsprobleme und Bestellprobleme
können mit dem Schlüsselwort volatile gelöst werden, da eine weitere Funktion von volatile darin besteht, die Optimierung der Neuordnung von Anweisungen zu verhindern eine Kopie und greift direkt auf den Hauptspeicher zu
. Was ist der Unterschied zwischen Volatilität und Synchronisierung?

Im Java-Speichermodell gibt es Hauptspeicher, und jeder Thread verfügt auch über einen eigenen Speicher (z. B. Register). Aus Leistungsgründen behält ein Thread eine Kopie der Variablen, auf die er zugreift, in seinem eigenen Speicher. Auf diese Weise kann es zu Situationen kommen, in denen der Wert derselben Variablen im Speicher eines Threads zu einem bestimmten Zeitpunkt möglicherweise nicht mit dem Wert im Speicher eines anderen Threads oder dem Wert im Hauptspeicher übereinstimmt. Das Deklarieren einer Variablen als flüchtig bedeutet, dass die Variable jederzeit von anderen Threads geändert werden kann und daher nicht im Thread-Speicher zwischengespeichert werden kann.

Nutzungsszenarien

Volatile Variablen können nur in begrenzten Situationen zum Ersetzen von Sperren verwendet werden. Damit flüchtige Variablen eine ideale Thread-Sicherheit bieten, müssen die folgenden zwei Bedingungen gleichzeitig erfüllt sein:
1) Der Schreibvorgang auf die Variable hängt nicht vom aktuellen Wert ab.
2) Die Variable ist nicht in einer Invariante mit anderen Variablen enthalten.

volatile eignet sich am besten für Situationen, in denen ein Thread schreibt und mehrere Threads lesen.
Wenn mehrere Threads gleichzeitig schreiben, müssen Sie stattdessen dennoch Sperren oder threadsichere Container oder atomare Variablen verwenden.

synchronisiert

Wenn es zum Ändern einer Methode oder eines Codeblocks verwendet wird, kann sichergestellt werden, dass höchstens ein Thread den Code gleichzeitig ausführt .

  1. Wenn zwei gleichzeitige Threads auf den synchronisierten (diesen) synchronisierten Codeblock im selben Objektobjekt zugreifen, kann jeweils nur ein Thread ausgeführt werden. Ein anderer Thread muss warten, bis der aktuelle Thread die Ausführung dieses Codeblocks abgeschlossen hat, bevor er diesen Codeblock ausführen kann.
  2. Wenn jedoch ein Thread auf einen synchronisierten (diesen) synchronisierten Codeblock eines Objekts zugreift, kann ein anderer Thread weiterhin auf den nicht synchronisierten (diesen) synchronisierten Codeblock im Objekt zugreifen.
  3. Besonders kritisch ist, dass, wenn ein Thread auf einen synchronisierten (diesen) synchronisierten Codeblock des Objekts zugreift, der Zugriff anderer Threads auf alle anderen synchronisierten (diesen) synchronisierten Codeblöcke des Objekts blockiert wird.
  4. Wenn ein Thread auf einen synchronisierten (diesen) synchronisierten Codeblock eines Objekts zugreift, erhält er die Objektsperre dieses Objekts. Dadurch wird der Zugriff anderer Threads auf alle synchronisierten Codeteile des Objektobjekts vorübergehend blockiert .
    Was ist der Unterschied zwischen Volatilität und Synchronisierung?
    Gemeinsame Ressourcen und Objekte zum Hinzufügen, Löschen und Ändern.

Lock

Ab JDK 5.0 bietet Java einen leistungsfähigeren Thread-Synchronisationsmechanismus – die Synchronisation wird durch explizite Definition von Synchronisationssperrobjekten erreicht, und Synchronisationssperren fungieren als Sperrobjekte.

Die java.util.concurrent.Locks.Lock-Schnittstelle ist ein Tool zur Steuerung des Zugriffs mehrerer Threads auf gemeinsam genutzte Ressourcen. Sperren bieten exklusiven Zugriff auf gemeinsam genutzte Ressourcen. Es kann jeweils nur ein Thread das Lock-Objekt sperren, bevor er mit dem Zugriff auf die gemeinsam genutzten Ressourcen beginnt.

Die ReentrantLock-Klasse implementiert Lock, das die gleiche Parallelität und Speichersemantik wie synchronisiert aufweist. Bei der Implementierung der Thread-sicheren Steuerung wird ReentrantLock häufiger verwendet und kann Sperren anzeigen und Sperren freigeben.

Was ist der Unterschied zwischen Volatilität und Synchronisierung?

Der Unterschied

volatile und synchronisierted

  • volatile ist ein variabler Modifikator, während synchronisiert sich auf einen Codeabschnitt oder eine Methode auswirkt .

  • volatile synchronisiert lediglich den Wert einer Variablen zwischen Thread-Speicher und „Haupt“-Speicher, während synchronisiert den Wert aller Variablen durch Sperren und Entsperren eines Monitors synchronisiert. Synchronisiert verbraucht offensichtlich mehr Ressourcen als flüchtig.

  • flüchtig führt nicht zu einer Thread-Blockierung; synchronisiert kann zu einer Thread-Blockierung führen.

  • volatile garantiert die Sichtbarkeit von Daten, kann jedoch nicht die Atomizität garantieren; während synchronisiert die Atomizität und auch indirekt die Sichtbarkeit garantieren kann, da die Daten im privaten Speicher und im öffentlichen Speicher synchronisiert werden.

  • Variablen, die als flüchtig markiert sind, werden vom Compiler nicht optimiert; als synchronisiert markierte Variablen können vom Compiler optimiert werden.
  • Thread-Sicherheit umfasst zwei Aspekte: Atomizität und Sichtbarkeit. Der Synchronisierungsmechanismus von Java konzentriert sich auf diese beiden Aspekte, um Thread-Sicherheit zu gewährleisten.
Das Schlüsselwort volatile wird hauptsächlich verwendet, wenn mehrere Threads erkennen können, dass Instanzvariablen geändert wurden, und der neueste Wert verwendet werden kann. Das heißt, wenn mehrere Threads gemeinsam genutzte Variablen lesen, kann der neueste Wert verwendet werden.


Das Schlüsselwort volatile veranlasst den Thread, jedes Mal Variablen aus dem gemeinsam genutzten Speicher zu lesen, anstatt sie aus dem privaten Speicher zu lesen, wodurch die Sichtbarkeit synchronisierter Daten sichergestellt wird. Aber bitte beachten Sie: Wenn Sie die Daten in der Instanzvariablen ändern

Zum Beispiel: i++, also i=i+1, dann ist eine solche Operation eigentlich keine atomare Operation, das heißt, sie ist nicht threadsicher. Die Operationsschritte des Ausdrucks i++ sind wie folgt unterteilt:
1) Holen Sie sich den Wert von i aus dem Speicher.
2) Berechnen Sie den Wert von i;
3) Schreiben Sie den Wert von i in den Speicher.
Wenn ein anderer Thread bei der Berechnung des Werts in Schritt 2 auch den Wert von i ändert, werden zu diesem Zeitpunkt fehlerhafte Lesedaten im Namen angezeigt. Die Lösung besteht darin, das synchronisierte Schlüsselwort zu verwenden. Volatile selbst beschäftigt sich also nicht mit der Atomarität von Daten, sondern zwingt das Lesen und Schreiben von Daten dazu, sich zeitnah auf den Hauptspeicher auszuwirken.

synchronisiert und gesperrt

Sperre ist eine explizite Sperre (manuell öffnen und schließen, vergessen Sie nicht, die Sperre auszuschalten), synchronisiert ist eine implizite Sperre und die Sperre wird automatisch freigegeben, wenn sie den Gültigkeitsbereich verlässt .
Lock sperrt nur Codeblöcke, synchronisiert kann auf Codeblöcke und Methoden einwirken.
Mit Lock Lock verbringt JVM weniger Zeit mit der Threadplanung und erzielt eine bessere Leistung. Und verfügt über eine bessere Skalierbarkeit (Bereitstellung von mehr Unterklassen).
Verwendungssequenz: Sperren->synchronisierter Codeblock (hat den Methodenkörper betreten und entsprechende Ressourcen zugewiesen) ->synchronisierte Methode (außerhalb des Methodenkörpers).

Weitere Kenntnisse zum Thema Programmierung finden Sie unter: Lernkurse zum Programmieren! !

Das obige ist der detaillierte Inhalt vonWas ist der Unterschied zwischen Volatilität und Synchronisierung?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage