在《基于線程、并發的基本概念(詳解)》中,我們利用synchronized關鍵字、Queue隊列、以及Object監視器方法實現了生產者消費者,介紹了有關線程的一些基本概念。Object類提供的wait的方法和notifyAll方法,與之對應的是Condition接口提供是await和signalAll。await(或wait)是讓當前線程進入等待狀態并釋放鎖,signalAll(或notifyAll)則是喚醒等待中的線程,使得等待中的線程有競爭鎖的資格,注意只是資格,并不代表被喚醒的線程就一定會獲得鎖。
Condition接口的具體實現還是在AbstractQueuedSynchronizer中的內部實現的——AbstractQueuedSynchronizer$ConditionObject。ConditionObject中維護了一個“等待隊列”,注意這個和AQS同步器維護的“同步隊列”不同。AQS所維護的同步隊列是當前等待資源(同步狀態)的隊列,當前線程獲取同步狀態失敗時,同步器會將當前線程以及等待狀態等信息構造成一個節點并加入到同步隊列中,同時阻塞當前線程,當同步狀態被所持有的線程釋放時會將同步隊列中的首節點喚醒重新獲取同步狀態。而每個Condition維護一個等待隊列,該隊列的作用是一個等待signal信號的隊列。這兩者之間的關系是一個協同的關系,用下圖的說明它們之間的協同過程:
1. AQS的同步隊列如下圖所示,一個頭結點head指向隊首,一個tail指向隊尾,當線程調用lock()方法獲取鎖而未成功時,線程被構造成節點加入到隊尾。(圖中NodeA是同步隊列的第一個節點,也就是獲得同步狀態的節點)
2.NodeA調用await()方法時,NodeA從AQS同步隊列中移除,自然也就釋放了鎖,NodeA此時被加入到Condition的等待隊列中,等待signal信號,如下圖所示。
3.執行完第2步后,此時NodeB在同步隊列中處于第一個節點位置,即獲取到了鎖,如果NodeB此時執行signal(或者signalAll)方法,NodeA將會從Condition等待隊列中被移除即被喚醒,加入到同步隊列中,此時NodeA僅僅是被喚醒有了在同步隊列中爭奪資源的資格,并不代表被喚醒后就立即獲得鎖,如下圖所示。
4. 最后NodeB在signal執行完畢后,調用unLock方法釋放鎖,此時NodeA處于隊首,并爭奪同步狀態。
以上是AQS的“同步隊列”和Condition的“等待隊列”之間相互協作的過程,下面從源碼解析Condition的主要方法await、signal、signalAll。
public final void await() throws InterruptedException{ if (Thread.interrupted()) //線程被中斷則拋出中斷異常 throw new InterruptedException(); Node node = addConditionWaiter(); //將線程構造為Node節點 long savedState = fullyRelease(node); //釋放鎖,返回同步狀態 int interruptMode = 0; while (!isOnSyncQueue(node)) { //循環判斷當前節點是否在同步隊列中 LockSupport.park(this); if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) break; //檢查節點在處于等待狀態時是否被中斷 } //在跳出了循環,即被signal喚醒后重新加入了同步隊列后,開始重新競爭鎖 if (acquireQueued(node, savedState) && interruptMode != THROW_IE) //acquireQueued自旋獲取鎖,具體分析見《2.從AbstractQueuedSynchronizer(AQS)說起(1)——獨占模式的鎖獲取與釋放》中對獲取同步狀態的解析 interruptMode = REINTERRUPT; if (node.nextWaiter != null) unlinkCancelledWaiters(); //如果節點從等待狀態轉換為在同步隊列中,并且也已經獲得了鎖,此時將斷開此節點后面的等待節點 if (interruptMode != 0) reportInterruptAfterWait(interruptMode); }
網頁題目:類似Object監視器方法的Condition接口(詳解)-創新互聯
分享路徑:http://vcdvsql.cn/article20/pgico.html
成都網站建設公司_創新互聯,為您提供外貿建站、關鍵詞優化、Google、域名注冊、品牌網站建設、響應式網站
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯