包括:同步佇列,獨佔式同步狀態獲取與釋放、共享式同步狀態獲取與釋放
1.同步佇列
aqs依賴內部的同步佇列(乙個fifo雙向佇列)來完成同步狀態管理。當執行緒獲取同步狀態失敗時,同步器會將當前執行緒和等待狀態等資訊包裝成乙個節點並將其加入同步佇列,同時會阻塞當前執行緒。當同步狀態釋放時,會把首節點中的執行緒喚醒,使其再次嘗試獲取同步狀態。
節點是構成同步佇列的基礎,同步器擁有首節點和尾節點,沒有成功獲取同步狀態的執行緒會成為節點加入該佇列的尾部,其結構如下圖所示
上圖中:同步器包含了兩個節點型別的引用,乙個紙箱頭結點,另乙個指向尾節點。假設其中乙個執行緒獲取了(獨佔)鎖,則其他執行緒需要將其等待狀態等資訊構造成為乙個節點(node)將其存入同步佇列。如何安全的加入至佇列??通過基於cas的方法compareandsettail(node expect, node update)來實現原子性操作。
同步佇列遵循fifo,首節點是獲取成功狀態的節點,首節點的執行緒在釋放同步狀態時,將會喚醒後繼節點,然後後繼節點獲取同步狀態時將自己設定為首節點。並斷開原節點的後繼節點。`
因為只有乙個執行緒獲取到同步狀態,故不需要進行原子操作。
2.獨佔式同步狀態獲取與釋放
aqs的acquire(int arg)可以獲取同步佇列,該方法對中斷不敏感,執行緒不會從同步佇列中移除。這裡面主要完成的工作是同步狀態獲取、節點構造、加入同步佇列以及在同步佇列中自旋等操作,其主要邏輯是:
(1)呼叫自定義同步器的tryacquire(int arg)方法,該方法保證執行緒安全的獲取同步狀態
(2)如果獲取失敗,就構造乙個獨佔式(node.exclusive)的同步節點,並通過addwaiter方法加入到同步節點的尾部
(3)最後呼叫acquiredqueued方法,是的該節點以「死迴圈」的方式獲取同步狀態。如果獲取不到則阻塞節點中的執行緒,而被阻塞執行緒的喚醒主要依靠前驅節點的出隊或阻塞執行緒中斷來實現。
//先看上面的addnode方法
private node enq(final node node) else }}
}
在enq(final node node)方法將併發新增節點的請求通過通過cas變得「序列化」了。 佇列同步器
1 abstractqueuedsynchronizer 頭節點 獲取同步狀態成功的節點 尾節點 執行緒無法獲取到同步狀態,而被構造成節點,加入到同步佇列。加入佇列必須保證執行緒安全 compareandsettail node expect,node update 2 獨佔式同步 1 獲取同步狀態...
抽象佇列同步器AQS
aqs具體實現及內部原理 aqs同步佇列具體實現結構 private volatile int state 共享變數,使用volatile修飾保證執行緒可見性share共享 多個執行緒可同時執行,如reentrantreadwritelock.readlock cyclicbarrier count...
同步器AQS中的同步佇列與等待佇列
在單純地使用鎖,比如reentrantlock的時候,這個鎖元件內部有乙個繼承同步器aqs的類,實現了其抽象方法,加鎖 釋放鎖也只是涉及到aqs中的同步佇列而已,那麼等待佇列又是什麼呢?當使用condition的時候,等待佇列的概念就出來了。condition的獲取一般都要與乙個鎖lock相關,乙個...