11 JUC之AQS中的CLH佇列

2021-08-26 23:29:48 字數 2153 閱讀 2948

aqs內部維護著乙個fifo的佇列,即clh佇列。aqs的同步機制就是依靠clh佇列實現的。clh佇列是fifo的雙端雙向佇列,實現公平鎖。執行緒通過aqs獲取鎖失敗,就會將執行緒封裝成乙個node節點,插入佇列尾。當有執行緒釋放鎖時,後嘗試把隊頭的next節點占用鎖。

clh佇列結構

clh佇列由node物件組成,node是aqs中的內部類。

重要屬性

//用於標識共享鎖

static final node shared = new node();

//用於標識獨佔鎖

static final node exclusive = null;

/*** 因為超時或者中斷,節點會被設定為取消狀態,被取消的節點時不會參與到競爭中的,他會一直保持取消狀態不會轉變為其他狀態;

*/static final int cancelled = 1;

/*** 當前節點釋放鎖的時候,需要喚醒下乙個節點

*/static final int signal = -1;

/*** 節點在等待佇列中,節點執行緒等待condition喚醒

*/static final int condition = -2;

/*** 表示下一次共享式同步狀態獲取將會無條件地傳播下去

*/static final int propagate = -3;

/** 等待狀態 */

volatile int waitstatus;

/** 前驅節點 */

volatile node prev;

/** 後繼節點 */

volatile node next;

/** 節點執行緒 */

volatile thread thread;

//node nextwaiter;

clh佇列執行

執行緒呼叫acquire方法獲取鎖,如果獲取失敗則會進入clh佇列

public final void acquire(int arg)
2.addwaiter(node.exclusive)方法會將當前執行緒封裝成node節點,追加在隊尾。

private node addwaiter(node mode) 

}//前面cas更新失敗後,再enq方法中迴圈用cas更新直到成功

enq(node);

return node;

}

acquirequeued方法中會使執行緒自旋阻塞,直到獲取到鎖。

final boolean acquirequeued(final node node, int arg) 

/**更改當前節點前置節點的waitstatus,只有前置節點的waitstatus=node.signal,當前節點才有可能被喚醒。如果前置節點的waitstatus>0(即取消),則跳過取更前面的節點。

*/if (shouldparkafte***iledacquire(p, node) &&

//通過unsafe.park來阻塞執行緒

parkandcheckinterrupt())

interrupted = true;

}} finally

}

執行緒釋放鎖,從前面可以知道,獲取到鎖的執行緒會設定為clh佇列的頭部。這裡如果tryrelease返回true,且head的waitstatus!=0。就會更新head的waitstatus為0並且 喚醒執行緒head.next節點的執行緒。

public final boolean release(int arg) 

return false;

}

更新head的waitstatus為0並且喚醒執行緒head.next節點的執行緒

private void unparksuccessor(node node) 

是呼叫了unsafe.unpark,喚醒執行緒。

if (s != null)

locksupport.unpark(s.thread);

}

併發程式設計之AQS中的CLH佇列

在aqs類檔案的開頭,作者新增了很長一段注釋,向開發者解釋clh佇列,以及aqs對clh佇列的使用。aqs裡面的clh佇列是clh同步鎖的一種變形。其主要從兩方面進行了改造 節點的結構與節點等待機制。在結構上,aqs類引入了頭結點和尾節點,他們分別指向佇列的頭和尾,嘗試獲取鎖 入佇列 釋放鎖等實現都...

JUC併發基石之AQS原始碼解析 獨佔鎖的釋放

juc併發基石之aqs原始碼解析 獨佔鎖的獲取public final boolean release int arg return false 獨佔鎖的涉及到兩個函式的呼叫 1.tryrelease arg 該方法由aqs的子類來實現釋放鎖的具體邏輯 2.unparksuccessor h 喚醒後...

Java之 AQS在幾個同步工具類中的使用

工具類 工具類作用 工具類加鎖方法 工具類釋放鎖方法 sync覆蓋的方法 sync非覆蓋的重要方法 state的作用 鎖型別鎖維護 semaphore 控制同時訪問某個特定資源的運算元量 acquire 每次請求乙個許可都會導致計數器減少1,一旦達到了0,新的許可請求執行緒將被掛起 release ...