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: Gemäß dieser Ausführungsreihenfolge kann Thread B den von Thread A festgelegten a-Wert definitiv nicht lesen. Die Semantik von Multithreading hier ist Es wurde durch Neuordnung zerstört. Operation 3 und Operation 4 können auch nachbestellt werden, was hier nicht erläutert wird. Es besteht jedoch eine Kontrollabhängigkeitsbeziehung zwischen ihnen, da Operation 4 nur ausgeführt wird, wenn Operation 3 eingerichtet ist. Wenn im Code Steuerungsabhängigkeiten vorhanden sind, wirkt sich dies auf die Parallelität der Ausführung der Befehlssequenz aus. Daher verwenden Compiler und Prozessoren die Schätzung der Ausführung, um die Auswirkungen von Steuerungsabhängigkeiten auf die Parallelität zu überwinden. Wenn Operation 3 und Operation 4 neu angeordnet werden und Operation 4 zuerst ausgeführt wird, wird das Berechnungsergebnis vorübergehend im Neuordnungspuffer gespeichert. Wenn Operation 3 wahr ist, wird das Berechnungsergebnis in die Variable i geschrieben Durch Die obige Analyse hateine 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)!