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