AQS鎖的原理

synchronized是JVM層面實現(xiàn)的鎖,而AQS是JDK層面實現(xiàn)的鎖。
關(guān)于synchronized鎖,可以看之前寫的這篇:
synchronized鎖關(guān)鍵字的膨脹性與用法

其實AQS和synchronized在實現(xiàn)鎖的原理上是一樣的,只是AQS是借助了同步隊列去進行自旋和阻塞,利用條件隊列去實現(xiàn)Object的對象方法,去完成等待和喚醒。

我們要注意的是同步隊列是等待獲取鎖的隊列,條件隊列是曾經(jīng)獲取到鎖,但是因為類似(滿隊入隊/空隊出隊)這樣的阻塞行為,而避免一直阻塞,進行調(diào)節(jié)使用的。

廢話不多說,我們從一個實際的場景出發(fā)去講一下這個原理。

1、線程A,B,C想要搶占一個資源做操作;

2、線程A先得頭籌獲得了對象的鎖。在它持有資源的同時,其他線程就會被阻塞,依次加入到同步隊列中去,順序為B,C;

3、每一個Node入隊都會自旋檢查自己前一個節(jié)點是不是signal狀態(tài),如果是signal狀態(tài),就阻塞自己,等待喚醒;如果不是,就自旋【嘗試獲取鎖,獲取不到就嘗試將它變成signal狀態(tài)】這個過程;

4、當線程A執(zhí)行完畢后,它會釋放鎖,然后喚醒同步隊列的頭結(jié)點,這時候頭結(jié)點B就會去獲取鎖;

5、當B獲得鎖之后,他發(fā)現(xiàn)之前線程A的操作讓當前資源隊列的元素為空,而它要做的操作是一個take()操作。無法執(zhí)行,會一直阻塞。要怎么辦呢?

6、這時候就會把它添加到條件隊列當中,然后釋放鎖,讓其他線程獲取資源,直到滿足線程B執(zhí)行操作的條件為止;

7、釋放鎖之后,喚醒了同步隊列的頭結(jié)點C,此時C獲得了資源。它對著資源隊列執(zhí)行了put()操作;

8、此時,條件隊列中的節(jié)點B將被喚醒,從條件隊列轉(zhuǎn)移到同步隊列的隊尾中去;

9、等線程C執(zhí)行完put()操作,釋放鎖,然后喚醒了同步隊列中的第一個節(jié)點B;

10、然后線程B執(zhí)行take()操作。并發(fā)結(jié)束。

以上就是一個簡單的鎖模型。

對于鎖的狀態(tài)state,是一個int值。

還有一個超時時間。這些是子類自己去實現(xiàn)規(guī)則。

同步隊列和條件隊列的元素都是Node

Node中主要有這些參數(shù):

waitStatus 當前節(jié)點的狀態(tài)。主要有0(初始化),1(取消),-1(SINGAL)【同步隊列】,-2(CONDITION)【條件隊列】,-3(PROPAGATE )【共享鎖】

是排他鎖還是共享鎖是根據(jù)Node中的字段標記的。

nextWaiter,在條件隊列中,指下一個節(jié)點;在同步隊列中,指什么屬性的鎖。

Thread 綁定的當前線程。

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

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

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