Volatile-variable in Java
So, ich bin dieses Buch zu Lesen mit dem Titel Java Concurrency in der Praxis und ich bin stecken geblieben auf diese eine Erklärung, die ich kann nicht scheinen zu verstehen, ohne ein Beispiel. Dies ist das Zitat:
Wenn thread
A
schreibt eine flüchtige
variable und nachher threadB
liest, dass die gleiche variable, die Werte
alle Variablen wurden sichtbar
A
vor zu schreiben, um die flüchtige
variable sichtbarB
nach
Lesen Sie die volatile-variable.
Kann mir jemand ein Gegenbeispiel, warum "die Werte ALLER Variablen, die sichtbar A
vor dem schreiben auf die volatile-variable sichtbar B
NACH der Lektüre die volatile-variable"?
Ich bin verwirrt, warum alle anderen nicht-volatile-Variablen nicht sichtbar B
vor dem Lesen die volatile-variable?
um es einfach auszudrücken: die flüchtige Semantik der Bestellung garantiert, so dass, wenn etwas passiert vor der operation, um die flüchtigen (Lesen/schreiben) wäre es auch gelesen/geschrieben vor der operation, effektiv die gleiche Reihenfolge der Operationen. Andere Compiler UND Prozessoren ausführen dürfen aus -, um lese - /Schreibvorgänge und Ausführung erheblich steigern die Leistung.
Schauen Sie Probe und Erklärung hier: stackoverflow.com/questions/10620680/...
InformationsquelleAutor denniss | 2011-06-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
Thread B kann eine CPU-lokalen cache dieser Variablen. Ein Lesen einer volatile-variable wird sichergestellt, dass alle intermediate-cache-flush aus einem früheren schreiben, die zu den flüchtigen beobachtet.
Zum Beispiel, Lesen Sie den folgenden link, der zu dem Ergebnis kommt, die mit "Fixing Double-Checked-Locking mit Volatile":
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
Richtig. Java definiert volatil, so dass eine volatile-Lesen einer Variablen den gleichen Speicher-Effekte, wie ein synchronized-beginnen Sie, und ein flüchtig-schreiben der gleichen variable hat die gleiche memory-Effekte als synchronisiert-Ende. In anderen Worten, "wenn (flüchtig Lesen) { do-Arbeit; flüchtige-schreiben }" ist wie ein synchronized-block, der es erlaubt mehrere threads zur Ausführung tun-Arbeit an der gleichen Zeit.
flüchtig liest, nicht Spülen Sie den caches... (Sie Lesen Sie gerade die w/o-Neuordnung)
Nein, es spielt keine flush-cache, die cache-Spülung wird durchgeführt, indem der cache-Kohärenz-Protokoll und die hardware-Ebene. Im Allgemeinen alle Schreibvorgänge auf eine cache-Zeile statt, indem der Prozessor aktualisiert wird (in der Regel nicht gespült) durch schreiben der gleichen cache-Zeile von einem anderen Prozessor. Java-memory-Modell nicht respektieren hardware-Speicher-Modell genau, die meisten Modelle sind schwächer. (einige link infoq.com/presentations/click-crash-course-modern-hardware mit einer ausgezeichneten video-on-java-und hardware)
nach dem schreiben auf die volatile-variable thread Ein-Themen-memory-Zaun, damit alles, was geschrieben gespült werden. Da B liest irgendwie umgekehrter Reihenfolge, zuerst flüchtig, dann seien Sie konsistent sind. W/o die Bestellung von Regeln, die beiden threads sind erlaubt, um eine out-of-order-lese - /Schreibvorgänge. Dies ist, was im Grunde geschieht auf der hardware-Ebene (ich weiß nicht, abweichen mehr aus der java-spec), aber die Aussage, dass die caches geleert werden, doesesn nicht die Realität widerspiegeln. Solche Sachen verursachen würde, wie die 100-fache Leistung beeinträchtigen.
InformationsquelleAutor Brett Kail
Erklärt, eine flüchtige Java-variable heißt:
Nur für Ihre Referenz, Wenn Sie flüchtig ist erforderlich ?
Vom JLS §17.4.7 Gut Gebildet Ausführungen
Nützlicher Link : Was wissen wir wirklich über non-blocking-Parallelität in Java?
Ich glaube, in anderen Abschnitten des JCP erklären, dass Java-Memory-Modell ermöglicht die nichtflüchtigen Variablen im wesentlichen in beliebiger Reihenfolge gelesen werden; die Laufzeit ist frei, um die Reihenfolge der Ausführung von Anweisungen, wo es keinen Einfluss auf den Programmablauf.
Ja, absolut. Lesen volatile-variable ist wie der Eintritt in einen synchronisierten block, schreiben auf eine volatile-Variable ist, wie wenn man die synchronisierten block. Deshalb werden alle nicht-vars nicht sichtbar sind, B vor B liest volatile-variable.
99tm: Es ist darauf hinzuweisen, dass es Unterschiede zwischen primitiven und Objekten, da volatile nur über die Objekt-Referenz und nicht das Objekt selbst: Daher kann man nicht deklarieren Sie ein Objekt als volatile und final zusammen. Jedoch wird hierbei ein Objekt, das Finale ist viel schneller, in der Tat, da die Referenz ändert sich nie: Deshalb müssen Sie das final-Objekte, wo immer Sie können. Schließlich, mit flüchtigen Objekte muss noch Synchronisations - und/oder volatile-Variablen von selbst, wenn Sie es ändern, zumindest, wenn Sie schreiben wollen, konsistente Anwendungen.
+1. Ich besuchte ein interview vor einigen Tagen und ich wurde gebeten, über flüchtige und ich sagte, dass threads nicht cache den Wert, sondern holt den letzten Wert vom Hauptspeicher. Dann kam die Frage, wo im Hauptspeicher? Ich konnte keine Antwort auf diese? Können Sie bitte lassen Sie mich wissen, wo im Hauptspeicher die flüchtigen Objekte oder einfache primitive variable vom Typ int gespeichert?
InformationsquelleAutor sgokhales
Wenn eine variable nicht volatile, dann wird der compiler und die CPU, kann re-order-Anweisungen frei, wie Sie sehen passen, um auf für Leistung optimieren.
Wenn die variable wird nun erklärt, flüchtige, dann der compiler nicht mehr versucht zu optimieren, Zugriffe (liest und schreibt) auf diese variable. Es kann jedoch weiter optimieren und den Zugang für andere Variablen.
Zur Laufzeit, wenn eine volatile-variable zugegriffen wird, die JVM erzeugt entsprechende memory-Barriere Anweisungen an die CPU. Die memory-Barriere dient dem gleichen Zweck - die CPU wird auch verhindern, dass re-Bestellung von Anweisungen.
Wenn eine volatile-variable wird geschrieben (von thread A), werden alle Schreibvorgänge auf beliebige andere Variablen, die abgeschlossen sind (oder wenigstens erscheinen) und sichtbar gemacht, bevor das schreiben an das volatile-Variablen; dies wird oft durch eine memory-write-barrier-Instruktion. Ebenso werden keine reads auf die anderen Variablen, abgeschlossen sein wird (oder erscheint), bevor die
Lesen (thread B); dies wird oft durch eine Speicher-lese-Barriere-Anweisung. Diese Reihenfolge von Anweisungen, die erzwungen wird durch die Barriere(N), bedeutet, dass alle Schreibvorgänge sichtbar, wird sichtbar werden, B. Dies bedeutet jedoch nicht, daß jede erneute Bestellung von Anweisungen nicht passiert ist (der compiler durchgeführt haben kann Nachbestellung für weitere Anweisungen); es bedeutet einfach, dass wenn jeder schreibt sichtbar aufgetreten sind, wäre es sichtbar zu B. In einfacheren Worten, es bedeutet, dass strenge-Programm, um nicht beibehalten werden.
Punkt werde ich zu diesem Kommentar auf Speicher Barrieren und JVM Concurrency, wenn man verstehen will, wie die JVM-Themen-memory-Barriere Anweisungen, in feinere Details.
Fragen
gerade überprüft die verlinkten Artikel, ist es sehr gut.
Gibt es eine Garantie, dass eine Java-Implementierung verwenden Semantik ähnlich "voll" memory-Barrieren? Durch mein Verständnis, auch wenn das JIT-fügt eine memory barrier-Instruktion vor einem final-Feld zu speichern, zum Beispiel, das wäre nicht verhindern, dass es verschieben, was die JVM-spec würden, "unabhängig" code über die Barriere. Ich kenne kein Mittel, mit dem Java-code kann einfach sagen "ich will eine Erinnerung hier, und ich will nicht, etwas zog über Sie hinweg". In .NET ist ein synchronisierter block erreichen würde, aber in Java ist es nicht.
InformationsquelleAutor Vineet Reynolds
Threads sind erlaubt, cache-variable Werte, die andere threads schon seit aktualisiert Sie Lesen. Die
volatile
Schlüsselwort zwingt alle threads zu nicht-cache-Werte.InformationsquelleAutor Bohemian
Dies ist einfach eine zusätzliche bonus-Speicher-Modell erhalten Sie, wenn Sie die Arbeit mit volatile-Variablen.
Normalerweise (d.h. in der Abwesenheit von volatile-Variablen und Synchronisation), die VM machen kann Variablen von einem thread sichtbar für andere threads in beliebiger Reihenfolge es will, oder gar nicht. E. g. die Lesung thread Lesen konnte, eine Mischung von früheren Versionen von anderen threads variable Zuordnungen. Dies wird verursacht durch die threads, vielleicht auf verschiedenen CPUs laufen mit Ihren eigenen caches, die nur manchmal kopiert der "main memory", und zusätzlich durch code von der Neuordnung zur Optimierung Zwecke.
Wenn Sie eine volatile variable, so bald wie thread B Lesen Sie einen Wert X, dann ist das VM stellt sicher, dass alles, was Ein thread geschrieben hat, bevor er schrieb X ist auch sichtbar an B (Und auch alles was Ein habe garantiert sichtbar, transitiv).
Ähnliche Garantien gegeben werden für synchronisierte Blöcke und andere Arten von sperren.
InformationsquelleAutor Paŭlo Ebermann