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

2021-10-21 14:37:21 字數 2081 閱讀 8625

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

to enqueue into a clh lock, you atomically splice it in as new tail. to dequeue, you just set the head field.即要加入clh鎖,可以自動將其作為新尾部進行拼接。 要出隊,您只需設定頭欄位。
clh佇列由node物件組成,node是aqs中的內部類。

static final class node 

node()

node(thread thread, node mode)

node(thread thread, int waitstatus)

......

}

1.執行緒呼叫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;

}

enq方法:

private node enq(final node node)  else }}

}

假如有兩個執行緒,第乙個執行中,第二個在lch佇列裡面,在return node處,此時debug:

接下來是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

}

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

public final boolean release(int arg) 

return false;

}

private void unparksuccessor(node node) 

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

if (s != null)

locksupport.unpark(s.thread);

}

總結:

其實aqs的核心原理無非三點:1.自旋 2.lock.park()和unpark() 3.cas,順著這三個關鍵點和加鎖以及解鎖過程就可以理清

11 JUC之AQS中的CLH佇列

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

併發程式設計之AQS的同步原理

aqs abstractqueuedsynchronizer 抽象佇列同步器。aqs的同步狀態 aqs使用乙個int成員變數來表示同步狀態,通過內建的fifo佇列來完成獲取資源執行緒的排隊工作。aqs使用cas對該同步狀態進行原子操作實現對其值的修改。private volatile int sta...

併發程式設計之併發佇列

jdk 中提供了一系列場景的併發安全佇列。總的來說,按照實現方式的不同可分為阻塞佇列和非阻塞佇列,前者使用鎖實現,而後者則使用cas 非阻塞演算法實現。1 非阻塞佇列 concurrentlinkedqueue concurrentlinkedqueue是無界非阻塞佇列,內部使用單項鍊表實現 其中有...