Heim >Java >javaLernprogramm >[Bekämpfung der Java-Parallelität] ----- Neuordnung des Java-Speichermodells
Um die Leistung zu gewährleisten, ordnen Prozessoren und Compiler die Anweisungen häufig neu an. Sie können sie jedoch nicht beliebig sortieren. Es müssen die folgenden zwei Bedingungen erfüllt sein >
2. Eine Neuordnung ist nicht zulässig, wenn Datenabhängigkeiten bestehen.
int a = 1 ; //A int b = 2 ; //B int c = a + b; //CDie drei Operationen von A, B und C haben die folgende Beziehung: A und B haben keine Datenabhängigkeiten , Es besteht eine Datenabhängigkeitsbeziehung zwischen B und C, daher können A und B bei der Neuordnung beliebig sortiert werden, sie müssen jedoch vor C stehen. Die Ausführungsreihenfolge kann A –> B –> > A – >C. Unabhängig von der Ausführungsreihenfolge ist das Endergebnis C jedoch immer gleich 3. As-if-Serail-Semantik schützt Single-Thread-Programme, wodurch sichergestellt werden kann, dass das Endergebnis des Programms unter der Voraussetzung der Neuordnung immer konsistent ist. Tatsächlich haben sie für den obigen Code eine solche „Geschehen-vorher“-Beziehung:
public class RecordExample1 { public static void main(String[] args){ int a = 1; int b = 2; try { a = 3; //A b = 1 / 0; //B } catch (Exception e) { } finally { System.out.println("a = " + a); } } }Gemäß den Neuordnungsregeln können Operation A und Operation B neu angeordnet werden. Wenn sie neu angeordnet werden, löst B An aus Ausnahme auftritt (/ durch Null). Zu diesem Zeitpunkt wird Anweisung A definitiv nicht ausgeführt. Wird a immer noch gleich 3 sein? Wenn Sie dem Als-ob-seriell-Prinzip folgen, ändert sich das Ergebnis des Programms. Tatsächlich führt die JVM eine spezielle Verarbeitung für Ausnahmen durch, um die Semantik als ob seriell sicherzustellen = 3), obwohl dadurch die Logik in cathc komplizierter wird, lautet das Prinzip der JIT-Optimierung: Optimieren Sie die Logik im normalen Betrieb des Programms so weit wie möglich, auch auf Kosten der Komplexität der Catch-Block-Logik. Die Auswirkungen der Neuordnung auf MultithreadingIn einer Single-Thread-Umgebung kann die Neuordnung aufgrund der Semantik, als ob sie seriell ist, keinen Einfluss auf das Endergebnis haben, aber was ist mit einer Multi-Thread-Umgebung? ? Der folgende Code (klassische Verwendung von volatile):
public class RecordExample2 { int a = 0; boolean flag = false; /** * A线程执行 */ public void writer(){ a = 1; // 1 flag = true; // 2 } /** * B线程执行 */ public void read(){ if(flag){ // 3 int i = a + a; // 4 } } }Thread A führt write() aus, Thread B führt read() aus. Kann Thread B während der Ausführung a = 1 lesen? Tuch? Die Antwort ist nicht unbedingt (
Hinweis: X86CPU unterstützt keine Schreib-Schreib-Neuordnung. Wenn es auf x86 betrieben wird, ist dies definitiv a=1. LZ hat es lange Zeit nicht getestet und es schließlich erst später herausgefunden Überprüfen der Informationen ).
Da zwischen Operation 1 und Operation 2 keine Datenabhängigkeit besteht, kann eine Neuordnung durchgeführt werden. Es besteht keine Datenabhängigkeit zwischen Operation 3 und Operation 4. Sie können auch neu angeordnet werden, aber die Operationen 3 und 4 Es gibt eine Kontrollabhängigkeit zwischen Operationen 4. Wenn Operation 1 und Operation 2 neu angeordnet werden:eine Neuordnung, die sich nicht auf die Ausführungsergebnisse einer Single-Thread-Umgebung auswirkt, sondern die Ausführungssemantik von Multi-Threads zerstört .
Das Obige ist der Inhalt von [Java Concurrency] ----- Neuordnung des Java-Speichermodells Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn)!