在單純地使用鎖,比如ReentrantLock
的時候,這個鎖組件內部有一個繼承同步器AQS的類,實現了其抽象方法,加鎖、釋放鎖也只是涉及到AQS中的同步隊列而已,那麼等待隊列又是什麼呢?
當使用Condition
的時候,等待隊列的概念就出來了。Condition的獲取一般都要與一個鎖Lock相關,一個鎖上面可以生產多個Condition。
Condition接口的主要實現類是AQS的內部類ConditionObject
,每個Condition對象都包含一個等待隊列。該隊列是Condition對象實現等待/通知的關鍵。AQS中同步隊列與等待隊列的關係如下:
在Object的監視器模型上,一個對象擁有一個同步隊列與一個等待隊列,而AQS擁有一個同步隊列和多個等待隊列。
Object的監視器模型如下:
等待
調用condition的await方法,將會使當前線程進入等待隊列並釋放鎖(先加入等待隊列再釋放鎖),同時線程狀態轉爲等待狀態。
從同步隊列和阻塞隊列的角度看,調用await方法時,相當於同步隊列的首節點移到condition的等待隊列中
通知
調用condition的signal方法時,將會把等待隊列的首節點移到等待隊列的尾部,然後喚醒該節點。
被喚醒,並不代表就會從await方法返回,也不代表該節點的線程能獲取到鎖,它一樣需要加入到鎖的競爭acquireQueued方法中去,只有成功競爭到鎖,才能從await方法返回。