併發程式設計(六)抽象佇列同步器AQS解析
一、背景介紹
學習AQS前先了解一位巨佬,也就是java.util.concurrent包的作者Doug Lea
Java併發程式設計核心在於java.concurrent.util包,而JUC當中的大多數同步器實現都是圍繞著一些共同的基礎行為去實現的,比如:
- 等待佇列
- 條件佇列
- 獨佔獲取
- 共享獲取等
定義:而這些行為的抽象就是基於AbstractQueuedSynchronizer簡稱AQS,AQS定義了一套多執行緒訪問共享資源的同步器框架,是一個依賴狀態【state:表示資源的可用狀態】的同步器。
PS:AbstractQueuedSynchronizer位於java.util.concurrent.locks
PS:AQS底層有一個佇列容器來存放被阻塞的執行緒(用佇列的原因是因為要實現公平鎖的概念【排隊】)【AQS也是這個佇列的縮寫】
二、AQS具備特性
基本特性
- 阻塞等待佇列
- 共享/獨佔
- 公平/非公平
- 可重入
- 允許中斷
框架實現思路
- 1、定義內部類Sync繼承AQS
- 2、將同步器所有呼叫都對映到Sync對應的方法
state三種訪問方式
- getState()
- setState()
- compareAndSetState()
AQS定義兩種資源共享方式
- Exclusive-獨佔:只有一個執行緒能執行,如ReentrantLock
- Share-共享:多個執行緒可以同時執行,如Semaphore/CountDownLatch
三、AQS的兩種佇列
同步等待佇列
同步等待佇列也稱CLH佇列【作者姓名字母縮寫】,是一種基於雙向連結串列資料結構的佇列,是FIFO先入先出執行緒等待佇列,由阻塞機制實現。
條件等待佇列
佇列結構與上圖類似,就不重複贅述了。【condition條件佇列在後面會去學習】
四、Lock鎖內部的一些關鍵方法
isHeldExclusively()
作用:判斷該執行緒是否正在獨佔資源。
PS:只有用到condition才需要去實現它。
tryRelease(int state減少的量)【獨佔的鎖有對應的實現方法,如ReentrantLock】
作用:嘗試釋放資源,成功則返回true,失敗則返回false。
tryAcquire(int state增加的量)【獨佔的鎖有對應的實現方法,如ReentrantLock】
作用:嘗試獲取資源,成功則返回true,失敗則返回false。
tryAcquireShared(int)【共享的鎖有對應的實現方法,如CountDownLatch】
作用:嘗試獲取共享鎖,實現方式和獨佔鎖類似。
- 負數表示失敗
- 正數表示成功,且有剩餘資源
PS:state 狀態變數,state 的值代表著等待的執行緒數,比如初始化為 5,表示正在等待的執行緒數為 5,每次呼叫 countDown() 函式都會減1。
tryReleaseShared(int)【共享的鎖有對應的實現方法,如CountDownLatch】
作用:嘗試釋放共享資源,如果釋放後允許喚醒後續 等待結點返回true,否則返回false。