Peterson算法是一個實現互斥鎖的併發程序設計算法,能夠控制兩個線程訪問一個共享的單用戶資源而不發生訪問衝突。 參照《現代操做系統》,用Java實現了Peterson算法。java
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修改成本身的id,然後在while循環中陷入等待。測試
在聲明字段turn時,使用volaite
修飾,強制要求JVM保證變量在線程工做內存和主存之間一致性。spa