Viele Freunde haben vielleicht von dem Keyword Volatile gehört und haben es möglicherweise verwendet. Vor Java 5 war es ein kontroverses Schlüsselwort, da es häufig zu unerwarteten Ergebnissen führte. Erst nachdem Java 5 das volatile Schlüsselwort zurückgeführt hat, hat seine Vitalität wiedererlangt. Obwohl das volatile Schlüsselwort buchstäblich einfach zu verstehen ist, ist es nicht einfach, es gut zu verwenden.
1. Vorwort
JMM bietet eine variable Definition, endgültige, synchronisierte Blöcke, um die Sichtbarkeit sicherzustellen.
Bei Variablen, die mit volatilem modifiziertem modifiziert sind, liest der Thread bei jeder Verwendung der Variablen den modifiziertesten Wert der Variablen. Flüchtigen Sie sich leicht missbraucht und für atomare Operationen verwendet. Ich habe ein paar Testbeispiele geschrieben, Sie können es versuchen.
2. Hauptprogramm
public class main {public static void main (String [] args) löst InterruptedException aus {list <Thread> threadlist = new ArrayList <Thread> (); for (int i = 0; i <10; ++ i) {Thread = New Thread (New Runnable () {@overridepublic void run () {Single.HOLIDER.inStance.Add ();}}); ThreadList.add (Thread); Thread.start ();} für (Thread: ThreadList) Thread.join ();3. Testmodus -Test
1. Kein flüchtiges, kein synchronisiertes Synchron
Klasse Single {public int x = 0; public void add () {try {timeUnit.milliseconds.sleep (50);} catch (interruptedException e) {e.printstacktrace ();} ++ this.x;Ausgangsergebnisse: 8, 9 und 10 sind alle erschienen. Sie können mehr laufen und mehr versuchen und finden unterschiedliche Ergebnisse.
2. Es gibt volatile, aber keine synchronisiert
Klasse Single {public volatile int x = 0; public void add () {try {timeUnit.milliseconds.sleep (50);} catch (interruptedException e) {e.printstacktrace ();} ++ this.x;Ausgangsergebnis: Die maximale Anzahl von Vorkommen beträgt 9 und 10.
3. Kein flüchtiges, synchronisiertes synchronisiert
Klasse Single {public int x = 0; public synchronisierte void add () {try {timeUnit.milliseconds.sleep (50);} catch (interruptedException e) {e.printstacktrace ();} ++ this.x;Ausgabeergebnis: Egal wie oft Sie laufen, es wird 10 sein.
V.
öffentliche Klasse Lazysingleton {private int sonfield; private statische Lazysingleton -Instanz; private lazysingleton () {this.somefield = new random (). NextInt (200) +1; // (1)} public static lazysingleton getInstance () {if (instance == null) {// (2) synchronisiert (lazysingleton.class) {// (3) if (instance == null) {// (4) Instance = new lazysingleton (); // (5)}}} return Instance; // (6)} public int getomefield () {return this.somefield; // (7)}}Lassen Sie mich zunächst erklären, warum diese Schreibmethode in Java nicht funktioniert!
Nehmen wir an, dass Thread I zum ersten Mal die GetInstance () -Methode aufruft und dann auch Thread II die Methode getInStance () und Getomefield () -Methode aufruft. Was wir erklären wollen, ist, dass die Aussage von Thread I (1) nicht vor einer Aussage von Thread II (7) ist. Wenn Thread II die Anweisung (2) der GetInstance () -Methode ausführt, da der Zugriff auf die Instanz nicht im synchronen Block liegt, kann Thread II in Anweisung (5) das Schreiben von Thread I auf die Instanz (5) beobachten, dh der Wert der Instanz kann leer oder nicht leer sein. Wir gehen zunächst an, dass der Wert der Instanz nicht leer ist, also beobachten wir diesen Thread, den ich die Instanz schreibe. Zu diesem Zeitpunkt wird Thread II die Anweisung (6) ausführen und den Wert dieser Instanz direkt zurückgeben und dann die Methode von GetOMEField () in dieser Instanz aufrufen. Diese Methode wird auch ohne Synchronisation aufgerufen. Daher wird der gesamte Betrieb von Thread II ohne Synchronisation aufgerufen. Dies zeigt, dass es keine Beziehung zwischen der Aussage (1) von Thread I und der Aussage (7) von Thread II gibt. Dies bedeutet, dass Thread II möglicherweise nicht in der Lage ist, den von Thread I zu einer Art Fileed bei Anweisung (1) geschriebenen Wert zu beobachten. Dies ist das Problem mit DCL. Es ist lächerlich, oder? DCL sollte ursprünglich der Synchronisation entkommen, und es erreichte dieses Ziel. Genau deshalb wurde es schließlich bestraft. In solchen Programmen gibt es ernsthafte Fehler, obwohl die Wahrscheinlichkeit, dass ein solcher Fehler entdeckt wird, definitiv viel niedriger ist als die Wahrscheinlichkeit, die Lotterie zu gewinnen, und es flüchtig ist. Was erschreckender ist, ist, dass Sie auch dann nicht glauben, dass es von DCL verursacht wurde.
Mein Verständnis ist, dass sowohl Thread i als auch Thread II einen eigenen Arbeitspeicher haben. Nach dem Thread, den ich die Instanz erstellt habe, ist die Zeit zum Auffrischen des Speichers ungewiss. Daher ist es durchaus möglich, dass Thread II den von Thread I geschriebenen Wert I. zu einer Art Filed bei Anweisung (1) nicht beobachten kann.
Damit in Java 5 eine zusätzliche Vorschrift hinzugefügt wird:
• Schreiben Sie den Betrieb in das flüchtige Feld, bevor nachfolgende Lesevorgänge in das gleiche Feld.
Mit dieser Regel können wir Instanz als volatil deklarieren, das heißt: private volatile statische Lazysingleton -Instanz;
Nach dieser Regel können wir die Aussage von Thread I (5) -> Satz von Thread II (2) (dh Thread) erhalten, gemäß der Einzel -Thread -Regel, der Aussage von Thread I (1) -> Satz von Thread I (5) und Satz von Thread II (2) -> Satz von Thread II (7). Einiges in Erklärung (1) und das Programm kann das richtige Verhalten erhalten.
Ergänzung: Vor Java5 gibt es keinen Unterschied zwischen der synchronen Semantik des endgültigen Feldes und anderen Variablen. In Java5 werden nach dem Konstruktor, sobald die endgültige Variable im Konstruktor festgelegt ist (vorausgesetzt, diese Referenz ist nicht im Konstruktor), auf jeden Fall die im Konstruktor festgelegten Werte. Das Problem mit DCL ist nur, dass wir den Standardwert der Mitgliedsvariable des Objekts sehen, sodass wir die SOM -Feldvariable von Lazysingleton auf das endgültige festlegen können, damit sie in Java5 korrekt ausgeführt werden kann.
Der obige Inhalt ist das Wissen über volatile Schlüsselwörter in Java, die Ihnen vom Herausgeber vorgestellt wurden. Ich hoffe, es wird für alle hilfreich sein!