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.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).
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
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
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.
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); } } }
volatile realisiert die Optimierung des Verbots der Neuordnung von Anweisungen und vermeidet so das Phänomen der Programmstörung in einer Multithread-Umgebung.
Verstehen Sie zunächst ein Konzept, Memory Barrier (Memory Barrier), auch bekannt als Speicherbarriere ist eine CPU-Anweisung mit zwei Funktionen:
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 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
.
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 .
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.
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.
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!