指令重排是指:代碼執行順序和預期不一致。
代碼運行一般步驟為:
1、從內存中獲取指令解碼
2、計算值
3、執行代碼操作
4、把結果寫回內存
而寫回內存的操作比較耗時,CPU為了性能,可能不會等它完成,就進行對下一個指令解碼計算。
發生指令重排是CPU為了提高性能,但必須是對結果不影響的情況,比如:
a =1; b =2; 先計算a 或者 b 對結果來說沒有影響,就有肯能發送重排;而像 a = 5; b = a*3;這樣的代碼則不會發生重排。
一把發生指令重排在單線程中基本沒啥影響,當時在多線程中,同時操作一個數據,如果一個讀,一個寫,當寫的線程還沒寫回時,另一個線程已經開始讀取了,那么這個時候就會出現和預期不一致的結果。
寫一個可能生指令重排的代碼:
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 < 10; i++) {
a = 0;
flag = false;
// 線程1 更改數據
Thread t1 = new Thread(() -> {
a = 1;
flag = true;
});
// 線程2 讀取數據
Thread t2 = new Thread(() -> {
if (flag) {
a *= 1;
}
if (a == 0) {
System.out.println("指令重排了-->" + a);
}
});
t1.start();
t2.start();
// 合並線程,讓更改數據線程先運行完
t1.join();
t2.join();
}
}
}
運行以上代碼:

我的電腦配的是最新的4代內存,運行10次,發生兩次指令重排,如果用的是老一代的內存條,發生幾率應該是會大一些。
