Java多線程之volatile
阿新 • • 發佈:2019-03-16
class 單用戶 用戶 修飾 ava tar true java多線 代碼
當兩條線程同時執行的這一語句,各自將turn修改為自己的id,而後在while循環中陷入等待。
問題
Peterson算法是一個實現互斥鎖的並發程序設計算法,可以控制兩個線程訪問一個共享的單用戶資源而不發生訪問沖突。
參照《現代操作系統》,用Java實現了Peterson算法。
public class Mutex { private int turn; private boolean[] interested = new boolean[2]; public void enterRegion(int id) { int other = 1 - id; interested[id] = true; turn = id; while (turn == id && interested[other]){ } } public void leaveRegion(int id) { interested[id] = false; } }
測試代碼如下:
public class Peterson { public static final Mutex m = new Mutex(); public static void main(String[] args) { call(0); call(1); } public static void call(int i) { new Thread(()->{ while (true) { m.enterRegion(i); System.out.print("thead "+i+" start a job............"); System.out.println("thead "+i+" finish a job"); m.leaveRegion(i); } }).start(); } }
預期結果是終端交替不斷的輸出
thead 0 start a job............thead 0 finish a job
thead 1 start a job............thead 1 finish a job
事實是,程序陷入死鎖,終停止輸出內容。
原因
turn = id;
while (turn == id && interested[other]){
}
由於處理器為了提高處理速度,不直接和內存進行通訊,而是先將系統內存的數據讀到內部緩存(L1,L2或其他)後再進行操作,上面代碼中turn=id
在一個線程執行後,只是改變了緩存中的內容,這對另一個線程是不可見的。
解決辦法
在聲明字段turn時,使用volaite
修飾,強制要求JVM保證變量在線程工作內存和主存之間一致性。
Java多線程之volatile