java併發之隊列同步器

、注:僅根據自己的理解整理的零碎知識點(慢慢補充)

java中同步鎖的實現依賴於內部的隊列同步器,通過繼承實現隊列同步器獲取同步狀態和釋放同步狀態的方法。

隊列同步器內部通過一個int成員變量state來表示同步的狀態  佔有還是釋放(包括共享和獨佔),當線程獲取同步狀態失敗時當前線程被構造成一個節點加入到同步器的FIFO隊列中,同時阻塞當前線程,當同步狀態釋放時會把首節點的線程喚醒使其再次嘗試獲取同步狀態。同步對列中的節點保存獲取同步狀態失敗的線程引用、等待狀態、以及前驅和後繼節點。

獲取同步狀態失敗:

同步器中擁有首節點和尾節點,當一個線程成獲取同步狀態(鎖),其他準備獲取同步狀態的線程便無法獲取同步狀態,轉而被構造成節點加入到同步器的同步隊列的尾部。這個過程可能會有多個線程同時請求加入到尾部,需要保證尾節點的插入是原子性的,利用CAS操作來完成。

首節點同步狀態釋放:

首節點釋放同步同步狀態後會喚醒後繼節點,後集結點獲取同步狀態成功時會將自己設置爲首節點,這個過程中由於只有一個線會成功獲取同步狀態。因此設置首節點不需要CAS操作來保證。

Condition 實現:

作爲同步器的內部類,因爲condition的操作需要先獲取對應的鎖,每個condition獨享包括一個等待隊列,隊列中的每個節點代表了一個等待在該condition對象的線程,獲取鎖線程執行await()該線程釋放鎖,構造節點進入等待狀態。等待隊列節複用了同步隊列的節點類型。如果沒有先獲取同步狀態直接調用await()方法,則在釋放鎖的時候,雖然其節點狀態state默認值爲0表示獲取了同步狀態。但由於事先沒有該線程獲取同步狀態的信息在釋放時檢查到擁有同步狀態的線程並非當前線程而拋出異常。(在沒有同步的代碼塊中是不需要獲取和釋放同步狀態的操作的),

protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
}
在condition對象中,具有等待隊列,隊列的尾節點和首節點的添加和刪除不需要CAS來保證原子性,因爲操作conditon的線程已經獲取了鎖,通過鎖來保證了線程安全性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章