轉載請注明出處:http://blog.csdn.net/luonanqin
上一篇講了ReentrantLock的lock-unlock流程,今天這篇講講Condition的await-signal流程。
Condition類圖:
- Condition接口包含了多種await方式和兩個通知方法
- ConditionObject實現了Condition接口,是AbstractQueuedSynchronizer的內部類
- Reentrantlock的newCondition方法返回與某個lock實例相關的Condition對象
和release隊列一樣,Condition隊列也是虛擬隊列,每個Node通過nextWaiter進行關聯。因為Condition Node要變為release Node才可以解除阻塞,所以不需要prevWaiter,這一點下面會有說明。
大概的整個過程是:
調用await的線程都會進入一個Condition隊列。調用signal的線程每一次都會從firstWaiter開始找出未取消的Condition Node放到release隊列里,然后調用signal的線程在await或者unlock的時候執行release方法才有機會將其解除阻塞。相對於lock-unlock,正常的流程要簡單一些,但是對於中斷處理會更為復雜。
先看看調用await()至阻塞的過程
如圖所示,該過程可分為三個步驟:
- 新建Condition Node包裝線程,加入Condition隊列
- 釋放當前線程占用的鎖
- 阻塞當前線程
在阻塞當前線程之前,要判斷Condition Node是否在release隊列里。如果在的話則沒必要阻塞,可直接參與鎖競爭。關鍵代碼如下:

signal方法更簡單一些,就是從firstWaiter開始,找到一個沒有取消的Node放入release隊列。但是即使一開始找到的Node沒被取消,但是入隊列的時候也可能會被取消,因此代碼對這個情況做了點特殊處理。我根據自己的理解將代碼做了如下解釋:
下面我把調用await()的線程被解除阻塞后的流程也畫了一下:

以上就是await和signal的詳細流程。signalAll和signal很像,內部就是將Condition隊列里所有的Node都加入到release隊列中,僅此而已。
之后有時間我會把一些中斷處理也用流程圖描述下發出來。
之后有時間我會把一些中斷處理也用流程圖描述下發出來。
參考資料:
怎么理解Condition http://www.liuinsect.com/2014/01/27/how_to_understand_condition/