AQS

第一次聽(tīng)說(shuō)AQS,是滴滴的電話面試,之前毫無(wú)了解。后來(lái)看了幾篇博客,也是云里霧里。后來(lái)看源碼,事半功倍。現(xiàn)在做一些簡(jiǎn)單的總結(jié)。
J.U.C是基于AQS實(shí)現(xiàn)的,AQS是一個(gè)同步器,設(shè)計(jì)模式是模板模式。
核心數(shù)據(jù)結(jié)構(gòu):雙向鏈表 + state(鎖狀態(tài))
底層操作:CAS


public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

AQS中的int類型的state值,這里就是通過(guò)CAS(樂(lè)觀鎖)去修改state的值。lock的基本操作還是通過(guò)樂(lè)觀鎖來(lái)實(shí)現(xiàn)的。
獲取鎖通過(guò)CAS,那么沒(méi)有獲取到鎖,等待獲取鎖是如何實(shí)現(xiàn)的?我們可以看一下else分支的邏輯,acquire方法:

  1. tryAcquire:會(huì)嘗試再次通過(guò)CAS獲取一次鎖。
  2. addWaiter:通過(guò)自旋CAS,將當(dāng)前線程加入上面鎖的雙向鏈表(等待隊(duì)列)中。
  3. acquireQueued:通過(guò)自旋,判斷當(dāng)前隊(duì)列節(jié)點(diǎn)是否可以獲取鎖。

可以看到,當(dāng)當(dāng)前線程到頭部的時(shí)候,嘗試CAS更新鎖狀態(tài),如果更新成功表示該等待線程獲取成功。從頭部移除。
基本可以確認(rèn),釋放鎖就是對(duì)AQS中的狀態(tài)值State進(jìn)行修改。同時(shí)更新下一個(gè)鏈表中的線程等待節(jié)點(diǎn)。

獲取鎖流程

可以看到在整個(gè)實(shí)現(xiàn)過(guò)程中,lock大量使用CAS+自旋。因此根據(jù)CAS特性,lock建議使用在低鎖沖突的情況下。目前java1.6以后,官方對(duì)synchronized做了大量的鎖優(yōu)化(偏向鎖、自旋、輕量級(jí)鎖)。因此在非必要的情況下,建議使用synchronized做同步操作。

2019-04-18補(bǔ)充:
AQS定義兩種資源共享方式:Exclusive(獨(dú)占,只有一個(gè)線程能執(zhí)行,如ReentrantLock)和Share(共享,多個(gè)線程可同時(shí)執(zhí)行,如Semaphore/CountDownLatch)。

2019-07-19
這篇文章基本上就是搬運(yùn),非常粗糙。其實(shí)原文也沒(méi)有交代太多細(xì)節(jié),但是AQS的基本設(shè)計(jì)思想?yún)s寫(xiě)清楚了。

鳴謝:一文帶你理解Java中Lock的實(shí)現(xiàn)原理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容