AQS深入理解

2021-10-02 20:21:09 字數 3525 閱讀 9961

獨佔鎖的釋放 release方法

獨佔鎖的獲取與釋放總結

能響應中斷以及超時等待

共享鎖aqs實現的三個功能

對同步狀態的管理

對阻塞執行緒進行排隊

等待通知等底層功能的實現

aqs通過頭尾指標管理同步佇列的,獲取鎖失敗的執行緒入隊,釋放鎖對同步佇列中的執行緒進行通知

當共享資源被某個執行緒占有,其他請求該資源的執行緒將會阻塞,從而進入同步佇列。

node=

呼叫lock方法獲取獨佔鎖,獲取成功則執行緒執行,獲取失敗則當前執行緒入隊。而lock方法實際會呼叫aqs的acquire方法

獲取同步狀態成功,則返回

獲取同步狀態失敗,則先呼叫addwaiter方法再呼叫acquirequeued()方法 ——先將失敗程序入隊,然後再嘗試獲取獨佔鎖

public

final

void

acquire

(int arg)

若當前同步佇列尾節點為null,呼叫enq插入

若當前同步隊列為節點不為null,採用尾插入(compareandsettail方法)

通常來說如果cas操作失敗會繼續自旋(死迴圈)進行重試

private node addwaiter

(node mode)

}// 2.1. 當前同步佇列尾節點為null,說明當前執行緒是第乙個加入同步佇列進行等待的執行緒

enq(node)

;return node;

}

若當前執行緒是第乙個加入同步佇列時,呼叫compareandsethead(new node())構造頭節點

自旋不斷嘗試cas尾插入節點直到成功

private node enq

(final node node)

else}}

}

如果前驅節點是頭節點,並且成功獲取到同步狀態時,當前節點獲取鎖成功退出

獲取鎖失敗的話,將節點狀態設定為signal,然後呼叫locksupport.park方法阻塞該執行緒

節點狀態為siginal:標識當前執行緒處於阻塞狀態

// 排隊獲取鎖的過程

final

boolean

acquirequeued

(final node node,

int arg)

// 2.2 獲取鎖失敗,執行緒進入等待狀態等待獲取獨佔式鎖if(

shouldparkafte***iledacquire

(p, node)

&&//使用cas將節點狀態由initial設定成signal

parkandcheckinterrupt()

)//阻塞該執行緒

interrupted =

true;}

}finally

}

若同步狀態釋放成功,再判斷頭節點是否不為空以及該節點狀態值是否不為0,若成立執行unparksuccessor方法

public

final

boolean

release

(int arg)

return

false

;}

首先獲取頭節點的後繼節點,呼叫locksupport.unpark方法喚醒後繼節點

private

void

unparksuccessor

(node node)

if(s != null)

//後繼節點不為null時喚醒該執行緒

locksupport.

unpark

(s.thread)

;}

如果執行緒獲取鎖失敗,執行緒被封裝成node進行入隊操作,核心方法在於addwaiter()和enq(),enq()完成對同步佇列頭節點的初始化工作以及cas佇列操作失敗的重試

佇列中線程獲取鎖是乙個自旋的過程,若當前節點的前驅節點是頭節點而且成功獲取同步狀態時,將當前節點設定為頭節點,否則呼叫locksupport.park方法使當前執行緒阻塞

釋放鎖的時候,會通過locksupport.unpark方法喚醒頭節點的後繼節點

總的來說:

在獲取同步狀態時,aqs維護乙個同步佇列,獲取同步狀態失敗的執行緒會加入到佇列並且進行自旋,也就是不斷嘗試獲取鎖;如果前驅節點是頭節點並且成功獲得了同步狀態就會停止自旋,否則呼叫locksupport.park方法使當前執行緒阻塞。

在釋放同步狀態時,會通過locksupport.unpark方法喚醒頭節點的後繼節點

同步佇列通過頭指標與尾指標管理佇列,頭指標指向的節點是已經獲取到同步狀態的執行緒。

lock.lockinterruptibly方法,而該方法底層呼叫aqs的acquireinterrruptibly方法

lock.trylock(timeout,timeunit),底層呼叫aqs的tryacquirenanos方法

唯一不同:獲取鎖失敗後,對超時時間,對中斷的處理

public

final

void

acquireshared

(int arg)

private

void

doacquireshared

(int arg)}if

(shouldparkafte***iledacquire

(p, node)

&&parkandcheckinterrupt()

) interrupted =

true;}

}finally

}

自旋過程退出條件:前驅節點是頭節點,並且成功獲取到同步狀態

public

final

boolean

releaseshared

(int arg)

return

false

;}

private

void

doreleaseshared()

else

if(ws ==0&&

!compareandsetwaitstatus

(h,0

, node.propagate)

)continue

;// loop on failed cas}if

(h == head)

// loop if head changed

break;}

}

在共享鎖釋放過程中,對於能夠支援多個執行緒同時訪問的併發元件,必須保證多個執行緒安全釋放同步狀態。

這裡採用cas保證,當cas操作失敗,continue下一次迴圈重試

深入理解CAS與AQS

二 aqs 首先,cas是一種演算法,不是鎖cas,其實是個簡稱,全稱是 compare and swap,對比之後交換資料 expect 期望更新的值 一開始獲取的值 update 要更新的最新值 如果原子變數中的 value 值等於 expect,則使用 update 值更新該值並返回 true...

深入理解AQS原始碼解析一

三 最後小結一下 一 概念 我們談到併發,就不得不談reentrantlock鎖 而談到reentrantlock鎖,不得不談一下abstractqueuedsynchronized aqs 類如其名,抽象的佇列式的同步器,aqs定義了一套多執行緒訪問共享資源的同步器框架,許多同步類實現都依賴於它,...

8 深入理解juc 基於aqs的執行緒同步工具

1.hmaster在ha的情況下,掛了一台另一台可以立刻頂上。2.hmaster兩台全掛的情況下,對讀寫資料沒有任何影響,但是如果此時regionserver也掛了會報錯,並且影響讀寫。3.regionserver只要有一台存在,就可以讀寫資料。在其他regionserver掛了的時候,活著的reg...