HappenBefore
·你寫的代碼很可能根本沒按你期望的順序執行,因爲編譯器和CPU會嘗試重排指令使得代碼更快地運行。
·在虛擬機層面,爲了儘可能減少內存操作速度遠慢於CPU運行速度所帶來的CPU空置的影響,虛擬機會按照自己的一些規則將程序編寫順序打亂——即寫在後面的代碼在時間順序上可能會先執行,而寫在前面的代碼會後執行——以儘可能充分地利用CPU。
·在硬件層面,CPU會將接受到的一批指令按照其規則重排,同樣是基於CPU速度比緩存速度快的原因,和上一點的目的類似,只是硬件處理的話,每次只能在接收到的有限指令範圍內重排,而虛擬機可以在更大層面、更多指令範圍內重排。
public class HappenBefore {
private static int a = 0;
private static boolean flag = false;
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 100; i++) {
a = 0;
flag = false;
Thread t1 = new Thread(()-> {
flag = true;
});
Thread t2 = new Thread(()-> {
if(flag)
a += 1;
//指令重排
if(a == 0)
System.out.println("a is --> " + a);
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
}
實驗N次後得到如下結果
最後一次的結果顯然是不正常的,但其它輸出爲0的其實也不正常,根據順序結構,我們的代碼應該會先執行a+1的操作,然後再執行下面的代碼,這個時候a不應該爲0,也就是不應該打印。