Das code-Beispiel, die sich als "volatile" deklarieren sollte verwendet werden
Derzeit kann ich nicht verstehen, wenn wir volatile
zum deklarieren von Variablen.
Ich habe zu tun einige Studie und suchte einige Materialien über die für eine lange Zeit und weiß, dass, wenn ein Feld deklariert ist flüchtig, der compiler und die Laufzeit werden auf beachten Sie, dass diese variable geteilt wird, und dass Operationen sollten nicht nachbestellt werden mit anderen Speicher-Operationen.
Aber ich kann immer noch nicht verstehen, in welches Szenario wir sollten Sie nutzen. Ich meine, kann jemand irgendwelche Beispiel-code, die nachweisen können, dass die Verwendung von "volatile" - bringt nutzen oder Probleme zu lösen, zu vergleichen, um ohne es zu benutzen?
volatile
(und viele andere concurrency-Aspekte) sind sehr schwer zu beweisen, denn wenn du diese falsch, dann kann Sie immer noch erscheinen, um korrekt zu arbeiten und nicht ein problem, bis zu einer ganz bestimmten Bedingung Auftritt, und führt zu einem problem.- Ich habe versucht, diese selbst und produziert eine Prüfung, die übergabe von Werten zwischen Gewinde mit einem nicht-voltile Feld eine Milliarde mal erfolgreich, jedoch schlägt relativ schnell, wenn es die gleiche box ist geladen. Auch das timing der performance-Auswirkungen flüchtiger wird sehr schwierig werden, es hängt von vielen Faktoren ab.
- Haben Sie einen Blick auf diese post: stackoverflow.com/questions/7855700/...
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hier ist ein Beispiel, warum
volatile
notwendig ist. Wenn Sie entfernen Sie das Schlüsselwortvolatile
thread 1 kann nie kündigen. (Wenn ich getestet auf Java 1.6 Hotspot auf Linux, dies war in der Tat der Fall ist - Ihre Ergebnisse können variieren, da die JVM ist nicht verpflichtet, zu tun, keine Zwischenspeicherung von Variablen, die nicht markiertvolatile
.)running
, also thread 1 müssen nicht kündigen. Es ist jedoch nicht gezwungen, cache den Wert.volatile
(oder Synchronisation, oder etwas anderes welche Kräfte ein "passiert-vor" - Beziehung), thread 1 müssen nicht sehen, die änderung, die von thread 2.volatile
deaktiviert das caching!class TestThread extends Thread { private boolean running = true; public void run() { while(running) { //do something } } public void setStop() { running = false; } }
Die Methode 'setStop' wird aufgerufen in einem anderen thread, die Sie aufhalten will 'TestThread'. Damit ich hier nicht daneben läuft, wie flüchtig, so gibt es eine chance, dass TestThread nicht sofort angehalten (vielleicht sogar nie aufhört) nach setStop() aufgerufen wird, in einem anderen thread, richtig? Hier der sichere Weg ist, die ich brauche zu markieren, ausgeführt als flüchtige, richtig?Folgende ist ein Paradebeispiel für die Notwendigkeit von flüchtigen (in diesem Fall für die
str
variable. Ohne hotspot-Aufzüge den Zugriff außerhalb der Schleife (while (str == null)
) undrun()
nie beendet. Dies geschieht auf den meisten server JVMs.Eric, ich habe Ihre Kommentare zu Lesen und vor allem fällt mir auf
Das offensichtliche problem, das Sie haben können, sind compiler-reorderings, zum Beispiel die berühmten hochziehen wie erwähnt von Simon Nickerson. Aber lassen Sie uns davon ausgehen, dass es keine reorderings, dieser Kommentar kann eine gültige ein.
Weiteres Problem, das flüchtige löst mit 64-bit-Variablen (long, double). Wenn Sie schreiben, um einen langen oder Doppel, es wird behandelt wie zwei getrennte 32-bit speichert. Was passieren kann, mit einer gleichzeitigen schreiben ist die hohe 32 von einem thread geschrieben wird, um hohen 32-bits des Registers, während ein anderer thread schreibt der niedrigen 32 bit. Sie können dann eine lange, das ist weder das eine noch das andere.
Auch, wenn man sich die Speicher-Abschnitt, der die JLS werden Sie beobachten, Sie werden eine entspannte Speicher-Modell.
Das bedeutet, dass Schreibvorgänge dürfen nicht sichtbar sein (können sitzen in einem Speicher-Puffer) für eine Weile. Dies kann dazu führen, veraltete liest. Jetzt können Sie sagen, dass scheint unwahrscheinlich, und es ist, aber dein Programm ist falsch und hat das Potenzial zu scheitern.
Wenn Sie ein int, das Sie Inkrementieren für die Lebensdauer einer Anwendung-und Sie wissen (oder zumindest denken) die int-nicht überlaufen-dann musst du nicht ein upgrade auf eine lange, aber es ist immer noch möglich, es können. Im Falle eines Speicher-Sichtbarkeit von Problem, wenn Sie denken, es sollte keinen Einfluss auf Sie, Sie sollten wissen, dass es immer noch können und können zu Fehlern führen, die in Ihrer gleichzeitigen Anwendung, die äußerst schwierig zu identifizieren. Richtigkeit ist der Grund für die Verwendung von volatile.
Dem volatile-Schlüsselwort ist ziemlich Komplex und Sie brauchen, um zu verstehen, was es tut und nicht gut tun, bevor Sie es verwenden. Ich empfehle die Lektüre diese Sprache-Spezifikation Abschnitt, das erklärt es sehr gut.
Markieren Sie dieses Beispiel:
Was dies bedeutet ist, dass während
one()
j
ist nie größer alsi
. Jedoch einem anderen Thread ausgeführttwo()
vielleicht drucken Sie einen Wert vonj
die viel größer ist alsi
denn mal sagentwo()
läuft und holt sich den Wert voni
. Dannone()
läuft 1000 mal. Dann wird der Thread zwei bekommt endlich wieder geplant und nimmtj
das ist jetzt viel größer als der Wert desi
. Ich denke, dieses Beispiel perfekt zeigt den Unterschied zwischen volatile und synchronized - updates zui
undj
sind flüchtig, was bedeutet, dass die Reihenfolge, in der Sie geschehen im Einklang mit dem source-code. Doch die beiden updates passieren separat und nicht atomar so dass Anrufer kann sehen, Werte, Aussehen (zum Anrufer) inkonsistent sein.Kurz gesagt: Seien Sie sehr vorsichtig mit
volatile
!Ein minimalistisches Beispiel in java 8, wenn Sie entfernen volatile-Schlüsselwort, es wird nie enden.
Erweitern auf die Antwort von @jed-wesley-smith, wenn Sie diese drop in ein neues Projekt, nehmen Sie die
volatile
Schlüsselwort aus der iterationCount, und führen Sie es, es wird nie aufhören. Hinzufügen das volatile-Schlüsselwort entwederstr
oderiterationCount
würde dazu führen, den code zu Ende erfolgreich. Ich habe auch bemerkt, dass der Schlaf kann nicht kleiner sein als 5, die mit Java 8, aber vielleicht kann Ihre Laufleistung variieren mit anderen JVM /Java-Versionen.