摘要:前言本來準(zhǔn)備做源碼閱讀的幾千行看著太累了看了幾篇大神的文章后才基本搞懂附在這里閱讀本文前請(qǐng)先看懂的介紹和原理分析并發(fā)包源碼學(xué)習(xí)之框架四源碼分析接口實(shí)現(xiàn)接口一般看一個(gè)類實(shí)現(xiàn)的接口可以看出它的目的其實(shí)也是熟悉的目的主要是替代的方法的它是基于實(shí)現(xiàn)
前言
本來準(zhǔn)備做AbstractQueuedSynchronizer源碼閱讀的,幾千行看著太累了,看了幾篇大神的文章后才基本搞懂,附在這里,閱讀本文前請(qǐng)先看懂AQS
AbstractQueuedSynchronizer的介紹和原理分析
Java并發(fā)包源碼學(xué)習(xí)之AQS框架(四)AbstractQueuedSynchronizer源碼分析
Condition接口ConditionObeject實(shí)現(xiàn)Condition接口,一般看一個(gè)類實(shí)現(xiàn)的接口可以看出它的目的,其實(shí)也是熟悉API.
Condition的目的主要是替代Object的wait,notify,notifyAll方法的,它是基于Lock實(shí)現(xiàn)的.(而Lock是來替代synchronized方法).
public interface Condition { /** * 暫停此線程直至一下四種情況發(fā)生 * 1.此Condition被signal() * 2.此Condition被signalAll() * 3.Thread.interrupt() * 4.偽wakeup * 以上情況.在能恢復(fù)方法執(zhí)行時(shí),當(dāng)前線程必須要能獲得鎖 */ void await() throws InterruptedException; //跟上面類似,不過不響應(yīng)中斷 void awaitUninterruptibly(); //帶超時(shí)時(shí)間的await() long awaitNanos(long nanosTimeout) throws InterruptedException; //帶超時(shí)時(shí)間的await() boolean await(long time, TimeUnit unit) throws InterruptedException; //帶deadline的await() boolean awaitUntil(Date deadline) throws InterruptedException; //喚醒某個(gè)等待在此condition的線程 void signal(); //喚醒所有等待在此condition的所有線程 void signalAll(); }AQS中的ConditionObject
此類的構(gòu)造方法沒有參數(shù),所以不用講
整體講下這個(gè)ConditionObject的實(shí)現(xiàn),其實(shí)其維護(hù)兩個(gè)隊(duì)列,
Condition隊(duì)列,表示等待的隊(duì)列,其waitStatus=Node.Condition,由firstWaiter和lastWaiter兩個(gè)屬性操控.
Sync隊(duì)列,表示可以競(jìng)爭(zhēng)鎖的隊(duì)列,這個(gè)跟AQS一致,waitStatus=0;
await()方法呢就是把當(dāng)前線程創(chuàng)建一個(gè)Node加入Condition隊(duì)列,接著就一致循環(huán)查其在不在Sync隊(duì)列,如果當(dāng)前節(jié)點(diǎn)在Sync隊(duì)列里了,就可以競(jìng)爭(zhēng)鎖,恢復(fù)運(yùn)行了.
signal()方法就是把某個(gè)節(jié)點(diǎn)的nextWaiter設(shè)為null,再把其從Condition隊(duì)列轉(zhuǎn)到Sync隊(duì)列.
具體細(xì)節(jié)看下面源碼及注釋:
/** * 暫停此線程,直至許可滿足 * 只看沒有中斷和超時(shí)的await方法,其它處理中斷和超時(shí)的邏輯不care */ public final void awaitUninterruptibly() { Node node = addConditionWaiter(); //釋放當(dāng)前線程的鎖 int savedState = fullyRelease(node); boolean interrupted = false; //看自己在不在等待隊(duì)列,在 while (!isOnSyncQueue(node)) { //為了線程調(diào)度,禁用當(dāng)前的線程,直到許可可用 LockSupport.park(this); if (Thread.interrupted()) interrupted = true; } //獲取剛才釋放的鎖,參考AQS中acquire的講解吧 if (acquireQueued(node, savedState) || interrupted) selfInterrupt(); } /** * 添加一個(gè)等待Node到隊(duì)列中 */ private Node addConditionWaiter() { Node t = lastWaiter; // 如果尾節(jié)點(diǎn)被取消了,清理掉 if (t != null && t.waitStatus != Node.CONDITION) { unlinkCancelledWaiters(); t = lastWaiter; } // 新建一個(gè)Condition狀態(tài)的節(jié)點(diǎn),并將其加在尾部 Node node = new Node(Thread.currentThread(), Node.CONDITION); if (t == null) firstWaiter = node; else t.nextWaiter = node; lastWaiter = node; return node; } /** * 釋放當(dāng)前的state,最終還是調(diào)用tryRelease方法 */ final int fullyRelease(Node node) { boolean failed = true; try { int savedState = getState(); if (release(savedState)) { failed = false; return savedState; } else { throw new IllegalMonitorStateException(); } } finally { if (failed) node.waitStatus = Node.CANCELLED; } } /** * 是否還需要等待 */ final boolean isOnSyncQueue(Node node) { //如果狀態(tài)為Node.CONDITION,即還在Condition隊(duì)列中,還得再循環(huán)中等待 //如果其waitStatus不為Node.CONDITION,其前置節(jié)點(diǎn),即Sync的前置節(jié)點(diǎn)為null,為啥也繼續(xù)等著呢???誰來解答我的疑問 if (node.waitStatus == Node.CONDITION || node.prev == null) return false; //如果狀態(tài)不為Node.CONDITION,即不在Condition隊(duì)列了,有前置節(jié)點(diǎn)也有后置節(jié)點(diǎn),那么其一定在Sync隊(duì)列 if (node.next != null) return true; /* * 其前置節(jié)點(diǎn)為非null,但是也不在Sync也是可能的,因?yàn)镃AS將其加入隊(duì)列失敗.所以我們需要從尾部開始遍歷確保其在隊(duì)列 */ return findNodeFromTail(node); } / /** * 從尾部查找node節(jié)點(diǎn) */ private boolean findNodeFromTail(Node node) { Node t = tail; for (;;) { if (t == node) return true; if (t == null) return false; t = t.prev; } }signal()
/** * 釋放信號(hào) */ public final void signal() { //如果不是排它模式,則拋出IllegalMonitorStateException異常 if (!isHeldExclusively()) throw new IllegalMonitorStateException(); //將等待隊(duì)列的第一個(gè)節(jié)點(diǎn)出隊(duì)列,并將其加入AQS的鎖隊(duì)列 Node first = firstWaiter; if (first != null) doSignal(first); } /** * 真正的釋放信號(hào) */ private void doSignal(Node first) { do { //講first的nextWaiter設(shè)為null if ( (firstWaiter = first.nextWaiter) == null) lastWaiter = null; first.nextWaiter = null; } // 如果轉(zhuǎn)換隊(duì)列不成功且等待隊(duì)列不為null,繼續(xù)do while (!transferForSignal(first) && (first = firstWaiter) != null); } /** * 將一個(gè)節(jié)點(diǎn)從condition隊(duì)列轉(zhuǎn)換到Sync隊(duì)列 */ final boolean transferForSignal(Node node) { //所謂的Condition隊(duì)列和Sync隊(duì)列就在于waitStatus值 if (!compareAndSetWaitStatus(node, Node.CONDITION, 0)) return false; Node p = enq(node); int ws = p.waitStatus; if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL)) LockSupport.unpark(node.thread); return true; } /** * 喚醒所有等待在此condition的所有線程 */ public final void signalAll() { if (!isHeldExclusively()) throw new IllegalMonitorStateException(); Node first = firstWaiter; if (first != null) doSignalAll(first); } /** * 遍歷所有節(jié)點(diǎn),使其加入到Sync隊(duì)列 */ private void doSignalAll(Node first) { lastWaiter = firstWaiter = null; do { Node next = first.nextWaiter; first.nextWaiter = null; transferForSignal(first); first = next; } while (first != null); }
在此輸入正文
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/70093.html
摘要:前置文章為,如果不了解的基本和實(shí)現(xiàn)機(jī)制,建議先看一下這個(gè)文章。類似于和,常用于實(shí)現(xiàn)生產(chǎn)者消費(fèi)者。以下代碼是一個(gè)用的做的一個(gè)生產(chǎn)者消費(fèi)者例子。 前置文章為https://segmentfault.com/a/11...,如果不了解AQS的基本lock和unlock實(shí)現(xiàn)機(jī)制,建議先看一下這個(gè)文章。 Condition類似于wait和notify,notifyAll,常用于實(shí)現(xiàn)生產(chǎn)者消費(fèi)者。...
摘要:實(shí)現(xiàn)原理是通過基于單鏈表的條件隊(duì)列來管理等待線程的。中斷在轉(zhuǎn)移到同步隊(duì)列期間或之后發(fā)生,此時(shí)表明有線程正在調(diào)用轉(zhuǎn)移節(jié)點(diǎn)。在該種中斷模式下,再次設(shè)置線程的中斷狀態(tài)。 1. 簡(jiǎn)介 Condition是一個(gè)接口,AbstractQueuedSynchronizer 中的ConditionObject內(nèi)部類實(shí)現(xiàn)了這個(gè)接口。Condition聲明了一組等待/通知的方法,這些方法的功能與Objec...
摘要:實(shí)現(xiàn)原理是通過基于單鏈表的條件隊(duì)列來管理等待線程的。中斷在轉(zhuǎn)移到同步隊(duì)列期間或之后發(fā)生,此時(shí)表明有線程正在調(diào)用轉(zhuǎn)移節(jié)點(diǎn)。在該種中斷模式下,再次設(shè)置線程的中斷狀態(tài)。 1. 簡(jiǎn)介 Condition是一個(gè)接口,AbstractQueuedSynchronizer 中的ConditionObject內(nèi)部類實(shí)現(xiàn)了這個(gè)接口。Condition聲明了一組等待/通知的方法,這些方法的功能與Objec...
摘要:實(shí)現(xiàn)原理是通過基于單鏈表的條件隊(duì)列來管理等待線程的。中斷在轉(zhuǎn)移到同步隊(duì)列期間或之后發(fā)生,此時(shí)表明有線程正在調(diào)用轉(zhuǎn)移節(jié)點(diǎn)。在該種中斷模式下,再次設(shè)置線程的中斷狀態(tài)。 1. 簡(jiǎn)介 Condition是一個(gè)接口,AbstractQueuedSynchronizer 中的ConditionObject內(nèi)部類實(shí)現(xiàn)了這個(gè)接口。Condition聲明了一組等待/通知的方法,這些方法的功能與Objec...
摘要:與之相關(guān)的方法有三個(gè)原子性地修改都是類型,可見我們可以進(jìn)行,來定義的獲取與釋放從而實(shí)現(xiàn)我們自定義的同步器。 前言 源碼分析我認(rèn)為主要有兩個(gè)作用:滿足好奇心,我想每一個(gè)有追求的人都不會(huì)滿足于僅僅做一個(gè)API Caller實(shí)現(xiàn)功能就好,我們也想知道它到底是怎么實(shí)現(xiàn)的;借鑒與升華,當(dāng)我們明白了一個(gè)類的設(shè)計(jì)原理,在一定的情境下我們可以借鑒其設(shè)計(jì)哲學(xué),甚至針對(duì)我們自己特殊的業(yè)務(wù)場(chǎng)景對(duì)其進(jìn)行改良與...
閱讀 1697·2021-11-22 14:45
閱讀 1203·2021-11-17 09:33
閱讀 3403·2021-09-02 09:48
閱讀 1059·2019-08-30 15:54
閱讀 2816·2019-08-30 15:53
閱讀 2621·2019-08-30 12:54
閱讀 2309·2019-08-29 12:37
閱讀 2477·2019-08-26 13:58