ReentrantLock加鎖流程
加鎖成功流程
其實就是把state改為1,然後設置ExclusiveOwnerThread為當前線程 ** 加鎖失敗流程**
- 進入tryAcquire邏輯,這是state已經是1,結果仍然失敗
- 接下來進入addWaiter邏輯,構造Node隊列
- 下圖中黃色三角表示該Node的waitStatus狀態,其中0為默認正常狀態
- Node的創建是懶惰的
- 其中第一個Node成為Dummy,用來佔位,並不關聯線程
當前線程進入acquireQueued的邏輯
- acquireQueued會在第一個死循環中不斷嘗試獲得鎖,失敗後進入park阻塞
- 如果自己緊鄰着head(排第二位),那麼再次tryAcquire嘗試獲取鎖,當然這時state仍為1,失敗
- 進入shouldParkAfterFailedAcquire邏輯,將前驅node,即head的waitStatus改為-1,這次返回false
- shouldParkAfterFailedAcquire執行完畢回到acquireQueued(因為是死循環),再次tryAcquire嘗試獲取鎖,當然這時state仍為1,失敗
- 當再次進入shouldParkAfterFailedAcquire時,這是因為其前驅node的waitStatus已經是-1,這次返回true
- 進入parkAndCheckInterrupt,Thread-1 park(灰色表示)
ReentrantLock解鎖後是怎麼競爭的?
解鎖競爭成功
![]()
此時Thread-0釋放鎖,進入tryRelease流程,如果成功
- 設置exclusiveOwnerThread為null
- state=0
- 當前隊列不為null,並且head的waitStatus=-1,進入unparkSuccessor流程
- 找到隊列中離head最近的一個Node(沒取消的),unpark恢復其運行,本例中即為Thread-1
- 回到Thread-1的acquireQueued流程
此時Thread-1的Node在下一次進入循環的時候發現tryAcquire成功了,會設置
- <font style="color:rgb(38, 38, 38);">exclusiveOwnerThread為Thread-1,state=1</font>
- <font style="color:rgb(38, 38, 38);">head指向剛剛Thread-1所在的Node,該Node清空Thread</font>
- <font style="color:rgb(38, 38, 38);">原本的head因為從鏈表斷開,可以被垃圾回收</font>
解鎖競爭失敗
如果這時候有其他線程來競爭(非公平的體現),例如這時有Thread-4來了
如果不巧又被Thread-4搶先
- <font style="color:rgb(38, 38, 38);">Thread-4被設置為exclusiveOwnerThread,state=1,</font>
- <font style="color:rgb(38, 38, 38);">Thread-1再次進入acquireQueued流程,獲取鎖失敗,重新進入park阻塞</font>
總結
這篇文檔主要介紹了Java中ReentrantLock的加鎖和解鎖流程,包括成功和失敗的情況。以下是文檔的重點概括:
ReentrantLock加鎖流程
加鎖成功
- 將state設置為1。
- 設置ExclusiveOwnerThread為當前線程。
加鎖失敗
- 進入tryAcquire邏輯,如果state已經是1,則失敗。
- 進入addWaiter邏輯,構造Node隊列。
- Node的創建是懶惰的。
- 第一個Node成為Dummy,不關聯線程。
- 當前線程進入acquireQueued邏輯。
- 在死循環中嘗試獲取鎖,失敗則進入park阻塞。
- 如果自己緊鄰着head(排第二位),再次嘗試tryAcquire獲取鎖。
- 將前驅node(head)的waitStatus設置為-1。
- 進入parkAndCheckInterrupt,線程park。
ReentrantLock解鎖後的競爭
解鎖競爭成功
- Thread-0釋放鎖,進入tryRelease流程。
- 設置exclusiveOwnerThread為null。
- state設置為0。
- 如果當前隊列不為null,並且head的waitStatus為-1,進入unparkSuccessor流程。
- 找到隊列中離head最近的一個Node(未取消的),unpark恢復其運行(例如Thread-1)。
- Thread-1的Node在下一次循環時發現tryAcquire成功,設置exclusiveOwnerThread為Thread-1,state為1,head指向Thread-1所在的Node。
解鎖競爭失敗
- 如果有其他線程(如Thread-4)競爭。
- Thread-4可能搶先設置為exclusiveOwnerThread,state為1。
- Thread-1再次進入acquireQueued流程,獲取鎖失敗,重新進入park阻塞。
這篇文檔詳細描述了ReentrantLock在加鎖和解鎖過程中的內部機制,包括狀態的變更、隊列的構造、線程的阻塞和喚醒等關鍵步驟。