聊聊高并发(二十三)解析java.util.concurrent各个组件(五) 深入理解AQS(三)
這篇對AQS做一個總結。
上一篇帖了很多AQS的代碼,可以看出AQS的實現思路很簡單,就是提供了獲取acquire和釋放操作release,提供了
1. 可中斷和不可中斷的版本
2. 可定時和不可定時的版本
3. 獨享和共享的版本
?
看過之前實現各種自旋鎖系列的同學應該知道,在自旋鎖的實現中,獲取鎖和釋放鎖操作的邏輯基本如下:
自旋鎖獲取鎖操作
while 狀態不允許獲取鎖 {
????? 自旋
}
進入鎖之前設置某些狀態
?
自旋鎖釋放鎖操作
設置釋放鎖的狀態
if (允許后續線程獲取鎖){
??? 通知后續線程獲取鎖
}
?
而AQS的獲取和釋放操作也基本是這個邏輯,但是區別是它使用了阻塞操作,而不是自旋操作
AQS獲取操作 acquire
while (狀態不允許獲取操作){
??? if(需要阻塞獲取請求){
????????? 如果當前線程不在同步隊列中,那么將其插入隊列
????????? 阻塞當前線程
??? }else{
????????? 返回失敗
??? }
}
可能更新同步器狀態
如果線程位于同步隊列,則將其移出隊列
返回成功
}
?
AQS釋放操作 release
更新同步器狀態
if(新的狀態允許某個被阻塞的線程獲取成功){
????? 解除隊列中一個或多個線程的阻塞狀態
}
?
要實現AQS的獲取和釋放功能,至少需要考慮三方面
1. 共享狀態的原子修改,因為是在并發情況下
2. 線程的阻塞和喚醒,使用了Unsafe的park機制
3.?隊列的管理,使用了兩個隊列,同步隊列和條件隊列。同步隊列進行獲取和釋放操作,條件隊列進行阻塞和喚醒操作
?
AQS抽象類負責管理上述的三個方面,而具體的同步器實現類則需要根據基類暴露出的狀態相關的方法實現tryAcquire()和tryRelease()方法,以控制accquire和release操作。當狀態滿足時,tryAccquire方法要返回true,當新的狀態允許后續線程獲取時,tryRelease要返回true。另外這兩類方法都支持一個int的狀態參數,這個參數用于傳遞同步操作需要的狀態,不是所有的同步器都需要。
?
關于獲取操作和釋放操作的具體算法細節,可以參考Doug Lea的這篇論文,詳細分析了獲取操作和釋放操作的設計細節?The juc Synchronizer Framework中文翻譯版
?
AQS提供了一個上層的基類提供了構建同步器的底層構件,可以方便地使用它來創建各種類型的同步器。后面會聊聊juc包種的同步器是如何使用AQS來構建的,理解了AQS之后,我們也可以方便地利用它來創建自定義的同步器解決實際問題。
總結
以上是生活随笔為你收集整理的聊聊高并发(二十三)解析java.util.concurrent各个组件(五) 深入理解AQS(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 聊聊高并发(二十二)解析java.uti
- 下一篇: 聊聊高并发(二十四)解析java.uti