Beim Versuch zu verstehen, wie SubmissionPublisher
( Quellcode in Java SE 10, OpenJDK | docs ), eine neue Klasse, die in Version 9 zu Java SE hinzugefügt wurde, implementiert wurde, stieß ich auf einige API-Aufrufe, die VarHandle
mir bisher nicht bekannt waren:
fullFence
, acquireFence
, releaseFence
, loadLoadFence
Und storeStoreFence
.
Nachdem ich einige Nachforschungen angestellt habe, insbesondere in Bezug auf das Konzept der Gedächtnisbarrieren / -zäune (ich habe bereits von ihnen gehört, ja; aber ich habe sie nie benutzt und war daher mit ihrer Semantik nicht vertraut), denke ich, dass ich ein grundlegendes Verständnis dafür habe, wofür sie sind . Da sich meine Fragen jedoch aus einem Missverständnis ergeben könnten, möchte ich sicherstellen, dass ich sie überhaupt richtig verstanden habe:
Speicherbarrieren ordnen Einschränkungen in Bezug auf Lese- und Schreibvorgänge neu.
Speicherbarrieren können in zwei Hauptkategorien eingeteilt werden: unidirektionale und bidirektionale Speicherbarrieren, je nachdem, ob sie Einschränkungen für Lese- oder Schreibvorgänge oder für beide festlegen.
C ++ unterstützt eine Vielzahl von Speicherbarrieren , die jedoch nicht mit den von bereitgestellten übereinstimmen
VarHandle
. Einige der in verfügbaren SpeicherbarrierenVarHandle
bieten jedoch Reihenfolgeeffekte , die mit den entsprechenden C ++ - Speicherbarrieren kompatibel sind .#fullFence
ist kompatibel mitatomic_thread_fence(memory_order_seq_cst)
#acquireFence
ist kompatibel mitatomic_thread_fence(memory_order_acquire)
#releaseFence
ist kompatibel mitatomic_thread_fence(memory_order_release)
#loadLoadFence
und#storeStoreFence
haben kein kompatibles C ++ - Gegenstück
Das Wort kompatibel scheint hier wirklich wichtig zu sein, da sich die Semantik in den Details deutlich unterscheidet. Beispielsweise sind alle C ++ - Barrieren bidirektional, während dies bei Java nicht (unbedingt) der Fall ist.
- Die meisten Speicherbarrieren haben auch Synchronisationseffekte. Diese hängen insbesondere vom verwendeten Barrieretyp und den zuvor ausgeführten Barriereanweisungen in anderen Threads ab. Da die vollständigen Auswirkungen eines Barriereanweises hardwarespezifisch sind, bleibe ich bei den übergeordneten Barrieren (C ++). In C ++, zum Beispiel Änderungen vor einer Freigabesperrbefehl an einen Faden sichtbar sind Ausführung eines acquire Sperrbefehls.
Sind meine Annahmen richtig? Wenn ja, sind meine daraus resultierenden Fragen:
VarHandle
Verursachen die verfügbaren Speicherbarrieren irgendeine Art von Speichersynchronisation?Unabhängig davon, ob sie eine Speichersynchronisation verursachen oder nicht, wofür können Einschränkungen bei der Neuordnung in Java nützlich sein? Das Java-Speichermodell bietet bereits einige sehr starke Garantien hinsichtlich der Reihenfolge, wenn flüchtige Felder, Sperren oder
VarHandle
Operationen wie diese#compareAndSet
betroffen sind.
Für den Fall, dass Sie nach einem Beispiel suchen: Die oben genannte BufferedSubscription
innere Klasse von SubmissionPublisher
(Quelle oben verlinkt) hat in Zeile 1079 einen vollständigen Zaun eingerichtet (Funktion growAndAdd
; da die verlinkte Website keine Fragment-IDs unterstützt, nur STRG + F) ). Es ist mir jedoch unklar, wofür es da ist.
plain -> opaque -> release/acquire -> volatile (sequential consistency)
.