Das Java-Meymry-Modell schreibt vor, dass synchronize
-Bausteine, die auf demselben Monitor synchronisiert werden, eine Vorher-Nachher-Umsetzung der Variablen, die in diesen Blöcken geändert wurden, erzwingen. Beispiel:
In diesem Fall wird garantiert, dass Thread B x==true
angezeigt wird, solange Thread A diesen synchronized
-Block bereits übergeben hat. Jetzt bin ich dabei, viel Code neu zu schreiben, um die flexibleren (und besser gesagt: schnelleren) Sperren in java.util.concurrent
zu verwenden, insbesondere die ReentrantReadWriteLock
. So sieht das Beispiel so aus:
BEARBEITEN : Das Beispiel war kaputt, weil ich den Code falsch umgesetzt habe, wie in matt b beschrieben. Wie folgt behoben:
%Vor% Ich habe jedoch in der Spezifikation des Speichermodells keine Hinweise gesehen, dass solche Sperren auch die Notwendigkeit einer Bestellung implizieren. Wenn man sich die Implementierung ansieht, scheint sie sich auf den Zugriff auf flüchtige Variablen in AbstractQueuedSynchronizer
zu verlassen (zumindest für die Sun-Implementierung). Dies ist jedoch nicht Teil einer Spezifikation und darüber hinaus wird der Zugriff auf nichtflüchtige Variablen nicht wirklich berücksichtigt, die durch die durch diese Variablen gegebene Speicherbarriere abgedeckt wird, oder?
Also, hier sind meine Fragen:
synchronized
Blöcken? Grüße, Steffen
-
Kommentar zu Yanamon:
Sehen Sie sich den folgenden Code an:
%Vor%Nach dem, was ich verstanden habe, erzwingt die Speicherbarriere die zweite Ausgabe, um 2 zu zeigen, hat aber keinen garantierten Einfluss auf die anderen Variablen ...? Wie kann man das mit dem Zugriff auf eine flüchtige Variable vergleichen?
Aus dem API-Dokument :
Alle Lock-Implementierungen müssen erzwungen werden die gleiche Speichersynchronisation Semantik wie von der eingebauten bereitgestellt Monitorsperre, wie in The Java-Sprachspezifikation, Dritter Edition (17.4 Speichermodell):
%Vor%Erfolgloses Sperren und Entsperren Operationen und Wiedereintritt Sperren / Entsperren, nicht erfordern eine Speichersynchronisierung Effekte.
Abgesehen von der Frage, was die Semantik des Speichermodells garantiert, denke ich, dass es einige Probleme mit dem Code gibt, den Sie veröffentlichen.
Lock
-Implementierung verwenden, müssen Sie den synchronized
-Block nicht verwenden. Lock
besteht darin, dies in einem try-finally-Block zu tun, um ein versehentliches Entsperren des Schlosses zu verhindern (da die Sperre nicht automatisch bei der Eingabe eines Blocks aufgehoben wird, wie bei% co_de) % Block). Sie sollten synchronized
mit etwas ähnlichem verwenden:
Das Lesen und Schreiben von flüchtigen Variablen, die jetzt erzwungen werden, geschieht vor und nach der Operation. Das Schreiben in eine flüchtige Variable hat die gleiche Wirkung wie das Freigeben eines Monitors und das Lesen einer Variablen hat den Effekt, einen Monitor zu erfassen. Das folgende Beispiel macht es ein wenig klarer:
%Vor% Aber das alles gesagt, der von Ihnen bereitgestellte Beispielcode sah nicht so aus, als ob er wirklich ReentrantLock
, wie es entwickelt wurde, um verwendet zu werden.
Lock
mit dem integrierten Java-Code syncronized
macht den Zugriff auf das Schloss bereits single-threaded, so dass es dem Lock
nicht die Chance gibt, wirklich etwas zu tun. Lock
sollte gemäß dem folgenden Muster erfolgen. Dies wird in den Java-Dokumenten von %Co_de%
Yanamon, ich bin mir nicht sicher, ob Sie Recht haben - aber aus anderen Gründen als der Argumentation, die Sie machen.
Die Variable unguardedVariable kann im Thread "a" so neu angeordnet werden, dass ihr Wert auf 10 gesetzt wird, nachdem memoryBarrier auf true gesetzt wurde.
"Es gibt keine Garantie, dass Operationen in einem Thread in der vom Programm angegebenen Reihenfolge ausgeführt werden, solange die Neuordnung nicht innerhalb des Threads - erkannt wird, selbst wenn die Reihenfolge neu festgelegt wird ist offensichtlich für andere Threads "
Java Parallelität in der Praxis, Brian Goetz, p34
AKTUALISIERT: Was ich gesagt habe, stimmt im Falle des alten Speichermodells. Also, wenn du einmal-irgendwo-schreiben willst, dann steht mein Argument. In dem neuen Speichermodell ist dies jedoch nicht der Fall, da die Semantik, die die Neuordnung von nicht-flüchtigen Variablen bei Vorhandensein von flüchtigem Zugriff umgibt, strenger geworden ist (siehe Ссылка ).
Tags und Links java concurrency locking order synchronized