Wo ist die Lastbarriere für die volatile Aussage?

8

Ich habe dieses einfache Java-Programm geschrieben:

%Vor%

Dies erzeugt den folgenden disassemblierten Code für i ++ und j ++ (verbleibender disassemblierter Code entfernt):

%Vor%

Das verstehe ich über den folgenden Assembler-Code:

  • mov r10,7d5d0e898h: Verschiebt den Zeiger auf die IncrementClass.class, um r10
  • zu registrieren
  • inc dword ptr [r10 + 74h]: Erhöht den 4-Byte-Wert an der Adresse bei [r10 + 74h] (d. h. i)
  • mov r11d, dword ptr [r10 + 70h]: Verschiebt den Wert mit 4 Werten an der Adresse [r10 + 70h], um r11d zu registrieren (d. h. den Wert von j nach r11d zu verschieben)
  • inc r11d: Erhöht r11d
  • mov dword ptr [r10 + 70h], r11d: schreibe den Wert von r11d in [r10 + 70h], damit er für andere Threads sichtbar ist -lock add dword ptr [rsp], 0h: sperre die Speicheradresse, die durch den Stapelzeiger rsp dargestellt wird, und füge 0 hinzu.

JMM gibt an, dass vor jedem flüchtigen Lesen eine Ladespeicherbarriere vorhanden sein muss und nach jedem flüchtigen Schreibvorgang eine Speicherschranke vorhanden sein muss. Meine Frage ist:

  1. Warum gibt es vor dem Lesen von j in r11d keine Lastschranke?
  2. Wie stellt die Sperre und das Hinzufügen zu rsp sicher, dass der Wert von j in r11d wieder in den Hauptspeicher übertragen wird? Alles, was ich aus den Intel-Spezifikationen gelesen habe, ist, dass die Sperre der CPU eine exklusive Sperre für die angegebene Speicheradresse für die Dauer der Operation bereitstellt.
Salil Surendran 05.01.2015, 03:09
quelle

3 Antworten

5

Intel Prozessor x86 hat ein starkes Speichermodell .

Daher sind alle Sperren StoreStore, LoadLoad, LoadStore auf x86 nicht aktiv. Außer StoreLoad, das über mfence oder cpuid oder locked insn realisiert werden kann. Was Sie bereits mit Ihrem Assembler-Code bestätigen können. Andere Barrieren bedeuten nur eine Einschränkung der Compiler-Optimierung und -Transformation, so dass sie java nicht brechen Speichermodellspezifikation .

Als du auf dem Intel Prozessor liefest, nehme ich sein x86 an.

Bitte lesen Sie

  1. Ссылка als Referenz.

  2. Ссылка

  3. Ссылка

Lock ist kein Befehl, sondern ein Befehlspräfix (verhält sich wie eine storeLoad-Barriere).

  1. Was bedeutet der "lock" Befehl in x86 Assembly ?
  2. Warum wir vor CMPXCHG ein Sperrpräfix benötigen
veritas 05.01.2015 07:06
quelle
2

volatile Schlüsselwort in Java garantiert nur, dass die lokalen Threadskopien und Caches übersprungen werden und der Wert direkt vom Hauptspeicher geladen oder in den Hauptspeicher geschrieben wird. Es enthält jedoch keinen Sperrmechanismus. Das Lesen von volatile oder das Schreiben in volatile ist also atomar, aber eine Reihe von Lese- und Schreibvorgängen, wie Ihre obigen

j++

ist NICHT atomar, weil ein anderer Thread den Wert von j zwischen dem Lesen und Schreiben in die Variable im Hauptspeicher ändern kann. Um atomare Inkremente zu erreichen, müssen Sie CAS-Operationen verwenden, die in atomare Klassen in Java eingeschlossen sind, wie AtomicInteger usw. Alternativ können Sie atomare Methoden in Unsafe klasse zB verwenden, wenn Sie eine Low-Level-Programmierung bevorzugen. Unsafe.compareAndSwapInt etc.

    
Alex Suo 05.01.2015 03:23
quelle
0

Die Barriere kann von Ihrem JIT-Compiler optimiert werden, da Ihr Programm single-threaded ist (es gibt nur einen Thread - den Hauptthread), genauso wie eine Sperre unter einer single-threaded-Umgebung optimiert werden kann. Diese Optimierung ist unabhängig von der Prozessorarchitektur.

    
user2351818 09.02.2016 14:55
quelle