獨佔鎖的釋放 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...