java condition_(原创)Java的ReentrantLock(可重入锁)下的Condition
先來看一下這個Condition的使用場景,在LinkedBlockingQueue(鏈表的阻塞隊列)類中包含如下的定義,通過使用lock.newCondition()方法,可以獲得一個Condition對象,說明Condition與ReentrantLock有著重要的關聯關系。
Condition對象創(chuàng)建
通常它們的使用方式是如下這樣,注意線程1的condition.await()和線程2的condition.signal()方法,后面重點講解這兩個方法。
例子
Condition類是AQS(AbstractQueuedSynchronizer,抽象的隊列同步器)的內部類,我們重點來看下這個線程1的condition.await()方法,對里面的幾個重要方法進行重點的說明。
await()方法
Node node = addConditionWaiter();//將當前線程包裝成Node,然后放入條件等待隊列中,注意這個隊列和//外面的ReentrantLock的同步等待隊列是兩個不同的隊列,在喚醒時(也就是調用condition.signal()),會把//這個線程先從條件等待隊列中移除,然后轉移到ReentrantLock的同步等待隊列里面去,然后在同步等待隊列//中獲取鎖以后,才能真正的被執(zhí)行int savedState = fullyRelease(node);//在將當前線程放入到條件等待隊列中以后,這個方法會把當前線程//所持有的鎖釋放掉,這個時候ReentrantLock同步等待隊列中的某一個線程會獲得鎖,然后被激活int interruptMode = 0;while (!isOnSyncQueue(node)) {//判斷當前線程如果不存在于ReentrantLock同步隊列中,則將當前線程//中斷掛起,如果這個線程存在于ReentrantLock同步隊列中,那么它已經被中斷掛起,則不需要再次中斷掛起 LockSupport.park(this);總結來說就是,將當前線程封裝成Node,然后加入到條件等待隊列中,釋放線程持有的鎖,然后將此線程中斷掛起。
接下來我們重點來看下線程2的condition.signal()方法,對里面的幾個重要方法進行重點的說明。
signal()方法
if (!isHeldExclusively())//判斷此線程是不是ReentrantLock鎖的獨占線程,如果不是則拋出異常,換言之//只有是ReentrantLock鎖的獨占線程,才能進行喚醒操作,也就是說在執(zhí)行condition.await()//和condition.signal()方法時,線程必須拿到ReentrantLock鎖才可以進行,這也就是Condition //與ReentrantLock有著必要的關聯關系 throw new IllegalMonitorStateException(); Node first = firstWaiter;//拿到條件等待線程的第一個Node if (first != null) doSignal(first);//第一個Node不為null時,進行喚醒操作下面來看下doSignal(first)方法的執(zhí)行邏輯,重點看下其中的transferForSignal(first)方法。
doSignal()方法
transferForSignal()方法
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))//將Node的節(jié)點更新為0,如果更新失敗, //則代表此節(jié)點已經被取消了,直接返回失敗,遍歷下一個條件等待隊列的節(jié)點。 return false;Node p = enq(node);//重點方法,將當前節(jié)點由條件等待隊列轉移到ReentrantLock的同步等待隊列的隊尾中去 int ws = p.waitStatus;//此時被轉移到同步等待隊列的Node的waitStatus應該是0, if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))//將此Node節(jié)點的waitStatus更新為-1 LockSupport.unpark(node.thread);//此邏輯不會執(zhí)行,因為線程從條件等待隊列只是被轉移到了同步 //等待隊列,而且是隊尾的位置,如果同步等待隊列前面有有其他線程,則會優(yōu)先于它被喚醒。 return true;在執(zhí)行了condition.signal()方法后,會將條件等待隊列中的線程移除,然后轉移到ReentrantLock的同步等待隊列中,后面的邏輯就和ReentrantLock(可重入鎖)執(zhí)行同步等待隊列中的線程一樣了(這個邏輯不清楚可以查看我的此篇文章(原創(chuàng))Java的ReentrantLock(可重入鎖)詳解上篇)。
簡單總結下,Condition依賴于ReentrantLock,必須拿到ReentrantLock鎖以后,才可以進行await()和single()方法,在執(zhí)行了await()時,會釋放持有的ReentrantLock鎖,并把自己加入到條件等待隊列中去,在執(zhí)行了single()時,會把線程從條件等待隊列轉移到ReentrantLock的同步等待隊列中去,然后等待被真正的執(zhí)行。
總結
以上是生活随笔為你收集整理的java condition_(原创)Java的ReentrantLock(可重入锁)下的Condition的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python是多模型语言_Django多
- 下一篇: dom4j jar包_XML解析之DOM