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