Java 多線程 -- 指令重排(HappenBefore)


指令重排是指:代碼執行順序和預期不一致。

代碼運行一般步驟為:
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次,發生兩次指令重排,如果用的是老一代的內存條,發生幾率應該是會大一些。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM