讀源碼筆記 Java AbstractQueuedSynchronizer

AQS Condition

最近面試被問到java concurrent包下有哪些熟悉的,用過的工具。所以來回顧一下,這些工具的底層實現,AbstractQueuedSynchronizer。在網上看到了其餘人的一些技術博客,我將源碼貼出,分享下本身不一樣的看法。
clipboard.png
clipboard.pngjava

分析源碼

對於初看源碼的我來講,很奇怪,爲何明明「waitThread1」已經拿到鎖的狀況下,而「singalThread」還能獲取一樣的鎖而運行呢。這就得看源碼才能分析明白。
一開始waitThread拿到了鎖,而後調用了condition調用了await方法。
看看await方法:
clipboard.pngnode

  1. 首先方法中會構建一個node用來表示該node如今在Condition的queue中。Condition的queue維護着一連串的node,當前線程被包含在其中。面試

  2. 接下來fullyRelease方法會將AQS的當前狀態即state置爲0(這裏說的是具體的ReentrantLock的tryRelease實現方式,由於它是獨佔鎖。)fullyRelease其中還會將AQS中維護的queue(其中一樣是node,只是Condition中的node記錄的是等待condition的node,AQS中的queue是等待鎖的node)中的線程釋放出來。注意,執行完這一步以後,若另外一個線程singalThread因爲lock而得不到鎖,已經在AQS的queue中,處於wait狀態,這時他將被喚醒,而後獲取到鎖,從AQS的queue中刪除。工具

  3. 當singalThread執行完singal的之中,就會將condition中的node移到AQS的queue上去。
    具體代碼在condition中的signal方法中:spa

clipboard.png

將其node的狀態改成SIGNAL,注意這個時候通常node尚未被喚醒。
clipboard.png線程

一般上面這一句不會爲true,除非沒有能把目前node的狀態改成SIGNAL,或者node state大於0了,這個時候說明任務唄取消了,那麼以上兩種狀況都直接喚醒線程。除了上述兩種狀況外,由signalthread的unlock操做喚醒在AQS上的線程。隊列

總結

總的來講,操做順序是:ip

  1. waitthread lock源碼

  2. Signalthread lock 進入AQS隊列wait博客

  3. waitthread await 喚醒 Signalthread,Signalthread成功得到鎖

  4. Signalthread signal 將waitthread 狀態變爲signal並將其從condition queue轉到AQS queue

  5. Signalthread unlock 使waitthread再次得到鎖 執行餘下代碼。固然這是理由狀態下,爲了討論AQS及condition的原理,實際的操做時序也有可能變化。

相關文章
相關標籤/搜索