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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章