AQS源碼閱讀理解(uncompleted)
有head和tail
當acquire*操作的時候,如果我們定義的資源限制操作返回false時,會在tail端加入一個新的節點(Node裏面的所有基礎屬性都是volatile,用CAS設置tail指針)。
然後利用LockSupport.part(this)阻塞。
當release的時候,如果我們定義的資源操作返回true,會將head節點的下一個SIGNAL節點的thread喚醒。
被喚醒的那個線程會繼續嘗試執行tryAcquire,這時候會和新線程的請求發生爭用,ReentrantLock在這裏做了兩種策略,一種是判斷當前線程是否在鏈表的第一個位置(fair),一種是不做判斷直接爭用(unfair)
shouldParkAfterFailedAcquire會判斷當前加入的節點的前一個節點是否未獲得鎖(SIGNAL),如果未獲得,就返回true,告訴後面該part當前thread了
如果前個線程是CANCELLED的,刪除CANCELLED節點,返回false。如果是0,設置爲SIGNAL,返回false
也就是說,它做的主要做的是清理的工作,如果是false,就不會去part當前thread,而是再繼續走for循環。
這樣能保證每次醒來的節點會清理一遍前面的CANCELLED節點,讓p==head可以通過
Interruptibly式的獲取:其他線程對這個線程進行中斷,導致LockSupport.part(this)繼續執行,返回Thread.interrupted();外部會break-for,在for外層cancel該節點,並拋出InterruptedException
Nanos式的獲取:LockSupport.parkNanos(this, nanos),每次醒來都會檢查時間,如果時間超出,cancel該節點
方法:
獨佔獲取: acquire acquireInterruptibly tryAcquireNanos
tryAcquire acquireQueued doAcquireInterruptibly doAcquireNanos
共享獲取: acquireShared acquireSharedInterruptibly tryAcquireSharedNanos
tryAcquireShared doAcquireShared doAcquireSharedInterruptibly doAcquireSharedNanos
獨佔釋放: release
tryRelease
共享釋放: releaseShared
tryReleaseShared doReleaseShared
hasQueuedThreads hasContented getFirstQueuedThread isFirst fullIsFirst getQueuedLength
getQueuedThreads getExeclusiveQueuedThreads getSharedQueuedThreads getWaitingThreads
owns hasWaiters getWaitQueueLength
shouldParkAfterFailedAcquire
unparkSuccessor
setHeadAndPropagate
cancelAcquire
Condition
內部成員:firstWaiter、lastWaiter。內部包含一條Node鏈
內部方法:
signal、signalAll
await、awaitNanos、awaitUnit、await(long, TimeUnit)、awaitUninterruptibly
hasWaiters、getWaitQueueLength、getWaitingThreads
isOwnedBy(AQS)
執行await*操作時,會往末尾(lastWaiter)裏添加nextWaiter
然後釋放資源(release(state)),調用LockSupport.park(this)
執行signal操作時,會將firstWaiter移到sync queue末尾,調用的還是enq(node),並且將該node的waitStatus設置成SIGNAL,然後在程序執行lock.release時可以按正常資源釋放的操作進行。
調用阻塞的入口兩種,AQS.acquire和Condition.await
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.