JDK8-AQS源碼四之ConditionObject類

三月香巢已壘成,梁間燕子太無情!

前言

AQS的另外一個(gè)public的內(nèi)部類ConditionObject丽涩,有木有覺得有點(diǎn)像誰呢,對的裁蚁,它的粑粑就是前面介紹的Condition接口哦矢渊,他實(shí)現(xiàn)了 Condition和java.io.Serializable接口,ConditionObject內(nèi)部維護(hù)了一個(gè)單向的鏈表枉证,表示條件隊(duì)列矮男,它的節(jié)點(diǎn)狀態(tài)只能為獨(dú)占模式。

ps:條件隊(duì)列和同步隊(duì)列都是屬于等待隊(duì)列室谚,以前老是將等待隊(duì)列簡單理解為條件隊(duì)列了(Moves all threads from the wait queue for this condition to the wait queue for the owning lock.)毡鉴。

構(gòu)造函數(shù)

  //只有這一個(gè)無參構(gòu)造函數(shù)
  public ConditionObject() { }

屬性

    //條件隊(duì)列的首節(jié)點(diǎn)
    private transient Node firstWaiter;
    //條件隊(duì)列的尾結(jié)點(diǎn)
    private transient Node lastWaiter;

    //退出等待時(shí)重新中斷
    private static final int REINTERRUPT =  1;
    //退出等待是拋出InterruptedException
    private static final int THROW_IE    = -1;

方法

1.private方法

    //檢查節(jié)點(diǎn)的中斷狀態(tài), 在signalled之前被中斷了返回THROW_IE ,
    //在signalled之后中斷了秒赤,那么返回REINTERRUPT 
    //如果沒有被中斷猪瞬,那么返回0.
    private int checkInterruptWhileWaiting(Node node) {
        return Thread.interrupted() ?
            (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
            0;
    }

    //是重新中斷當(dāng)前線程,還是拋出異常
    //還是什么都不做入篮,取決于決定的模式陈瘦。
    private void reportInterruptAfterWait(int interruptMode)
        throws InterruptedException {
        if (interruptMode == THROW_IE)
            throw new InterruptedException();
        else if (interruptMode == REINTERRUPT)
            selfInterrupt();
    }

    //移除條件隊(duì)列中被cancled的節(jié)點(diǎn)。調(diào)用這個(gè)方法潮售,要求必須獲取了鎖痊项。
    //當(dāng)節(jié)點(diǎn)在等待條件時(shí)被取消,或者當(dāng)插入一個(gè)新的節(jié)點(diǎn)的時(shí)候
    //最后一個(gè)節(jié)點(diǎn)已經(jīng)被cancled了酥诽,那么將會調(diào)用這個(gè)方法鞍泉。
    private void unlinkCancelledWaiters() {
        Node t = firstWaiter;
        Node trail = null;
        while (t != null) {
            Node next = t.nextWaiter;
            if (t.waitStatus != Node.CONDITION) {
                //斷開與next的連接
                t.nextWaiter = null;
                if (trail == null)
                    firstWaiter = next;
                else
                    trail.nextWaiter = next;
                if (next == null)
                    lastWaiter = trail;
            }
            else
                trail = t;
            t = next;
        }
    }

    //將節(jié)點(diǎn)加入等待隊(duì)列中。
    //返回一個(gè)新的等待節(jié)點(diǎn)盆均。
    private Node addConditionWaiter() {
        Node t = lastWaiter;
        // 如果最后一個(gè)節(jié)點(diǎn)被cancledle塞弊,那么從首節(jié)點(diǎn)開始一次移除被cancled的節(jié)點(diǎn)
        if (t != null && t.waitStatus != Node.CONDITION) {
            unlinkCancelledWaiters();
            t = lastWaiter;
        }
        Node node = new Node(Thread.currentThread(), Node.CONDITION);
        if (t == null)
            firstWaiter = node;
        else
            t.nextWaiter = node;
        lastWaiter = node;
        return node;
    }

    //移除或者轉(zhuǎn)移節(jié)點(diǎn),直到找到一個(gè)沒有candled的節(jié)點(diǎn)或者節(jié)點(diǎn)為空泪姨。
    private void doSignal(Node first) {
        //first(非空)條件隊(duì)列中的第一節(jié)點(diǎn)
        do {
            if ( (firstWaiter = first.nextWaiter) == null)
                lastWaiter = null;
            //斷開與next的連接
            first.nextWaiter = null;
        } while (!transferForSignal(first) &&
                 (first = firstWaiter) != null);
                  // transferForSignal(first)返回false,說明節(jié)點(diǎn)被cancle了。
    }

    //將條件隊(duì)列中所有節(jié)點(diǎn)全部移除并轉(zhuǎn)移到條件隊(duì)列中
    //參數(shù)first條件隊(duì)列的頭結(jié)點(diǎn)非空
    private void doSignalAll(Node first) {
        //將條件隊(duì)列中的首尾節(jié)點(diǎn)置為null
        lastWaiter = firstWaiter = null;
        do {
            Node next = first.nextWaiter;
            //斷開連接
            first.nextWaiter = null;
            transferForSignal(first);
            first = next;
        } while (first != null);
    }

2.protected方法

    //如果condition是指定的同步對象創(chuàng)建的饰抒,則返回true
    final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
        return sync == AbstractQueuedSynchronizer.this;
    }

    //查詢是否有線程等待在當(dāng)前condition上肮砾。
    //如果有線程等待,那么返回true袋坑。
    protected final boolean hasWaiters() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
            if (w.waitStatus == Node.CONDITION)
                return true;
        }
        return false;
    }

    //返回等待在condition上的線程數(shù)量的估計(jì)值仗处。
    protected final int getWaitQueueLength() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        int n = 0;
        for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
            if (w.waitStatus == Node.CONDITION)
                ++n;
        }
        return n;
    }

    //返回可能等待在condition上的線程集合。
    protected final Collection<Thread> getWaitingThreads() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        ArrayList<Thread> list = new ArrayList<Thread>();
        for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
            if (w.waitStatus == Node.CONDITION) {
                Thread t = w.thread;
                if (t != null)
                    list.add(t);
            }
        }
        return list;
    }

3.public方法

    //將等待時(shí)間最長的節(jié)點(diǎn)從條件隊(duì)列轉(zhuǎn)移到同步隊(duì)列。
    public final void signal() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        Node first = firstWaiter;
        if (first != null)
            doSignal(first);
    }

    //將條件隊(duì)列所有的節(jié)點(diǎn)全部轉(zhuǎn)移到同步隊(duì)列中婆誓。
    public final void signalAll() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        Node first = firstWaiter;
        if (first != null)
            doSignalAll(first);
    }
   
    //不支持中斷的條件等待吃环。
    //1.保存getState返回的鎖狀態(tài)。
    //2.用保存的同步狀態(tài)作為參數(shù)洋幻,調(diào)用release郁轻,如果調(diào)用失敗,
    //3.拋出IllegalMonitorStateException文留。
    //4.阻塞直到signal好唯。
    //5.用保存的同步狀態(tài)作為參數(shù),調(diào)用acquire的acquireQueued版本重新獲取同步狀態(tài)燥翅。
    public final void awaitUninterruptibly() {
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        boolean interrupted = false;
        while (!isOnSyncQueue(node)) {
            LockSupport.park(this);
            if (Thread.interrupted())
                interrupted = true;
        }
        if (acquireQueued(node, savedState) || interrupted)
            selfInterrupt();
    }

    //可中斷的條件等待骑篙。
    //1.如果當(dāng)前線程被中斷了,那么拋出InterruptedException森书;
    //2.保存getState返回的鎖的狀態(tài)靶端;
    //3.以保存的同步狀態(tài)作為參數(shù)調(diào)用release,如果調(diào)用失敗凛膏,
    //拋出IllegalMonitorStateException杨名;
    //4.阻塞線程直到被signalled或者中斷;
    //5.以保存的同步狀態(tài)作為參數(shù)調(diào)用acquire的acquireQueued版本重新獲取同步狀態(tài)译柏;
    //6.如果在第4步阻塞的時(shí)候镣煮,被中斷了,那么拋出InterruptedException鄙麦。
    
    public final void await() throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            LockSupport.park(this);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        //如果節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)為空典唇,那么清理等待隊(duì)列中的被cancelled的節(jié)點(diǎn)
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
    }

    //指定時(shí)間的條件等待。
    //1.如果當(dāng)前線程被中斷了胯府,InterruptedException;
    //2.保存getState返回的鎖狀態(tài);
    //3.以保存的同步狀態(tài)作為參數(shù)調(diào)用release介衔,如果調(diào)用失敗,
    //那么拋出IllegalMonitorStateException;
    //4.阻塞當(dāng)前線程骂因,直到被signal炎咖,被中斷,或者等待時(shí)間到了;
    //5.以保存的同步狀態(tài)調(diào)用acquireQueued為參數(shù)寒波,重新獲取同步狀態(tài)乘盼。(?俄烁?);
    //6.在第4步阻塞的過程中绸栅,如果被中斷,拋出InterruptedException页屠。
    //返回剩余的等待時(shí)間粹胯。
    public final long awaitNanos(long nanosTimeout)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        final long deadline = System.nanoTime() + nanosTimeout;
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            if (nanosTimeout <= 0L) {
                transferAfterCancelledWait(node);
                break;
            }
            if (nanosTimeout >= spinForTimeoutThreshold)
                LockSupport.parkNanos(this, nanosTimeout);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
            nanosTimeout = deadline - System.nanoTime();
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
        return deadline - System.nanoTime();
    }


    //指定絕對的時(shí)間條件等待蓖柔。
    //1.如果當(dāng)前線程被中斷了,InterruptedException;
    //2.保存getState返回的鎖狀態(tài);
    //3.以保存的同步狀態(tài)作為參數(shù)調(diào)用release风纠,如果調(diào)用失敗况鸣,
    //那么拋出IllegalMonitorStateException;
    //4.阻塞當(dāng)前線程,直到被signal竹观,被中斷镐捧,或者等待時(shí)間到了;
    //5.以保存的同步狀態(tài)調(diào)用acquireQueued為參數(shù),重新獲取同步狀態(tài)(栈幸?愤估?);
    //6.在第4步阻塞的過程中,如果被中斷速址,拋出InterruptedException玩焰;
    //7.如果在第4步阻塞等待的時(shí)候,時(shí)間到了芍锚,那么返回false昔园,
    //否則,返回true并炮。
    public final boolean awaitUntil(Date deadline)
            throws InterruptedException {
        long abstime = deadline.getTime();
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        boolean timedout = false;
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            if (System.currentTimeMillis() > abstime) {
                timedout = transferAfterCancelledWait(node);
                break;
            }
            LockSupport.parkUntil(this, abstime);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
        return !timedout;
    }

    //指定時(shí)間的條件等待默刚。
    //1.如果當(dāng)前線程被中斷了,InterruptedException;
    //2.保存getState返回的鎖狀態(tài);
    //3.以保存的同步狀態(tài)作為參數(shù)調(diào)用release逃魄,如果調(diào)用失敗荤西,
    //那么拋出IllegalMonitorStateException;
    //4.阻塞當(dāng)前線程,直到被signal伍俘,被中斷邪锌,或者等待時(shí)間到了;
    //5.以保存的同步狀態(tài)調(diào)用acquireQueued為參數(shù),重新獲取同步狀態(tài)(癌瘾?觅丰?);
    //6.在第4步阻塞的過程中,如果被中斷妨退,拋出InterruptedException妇萄;
    //7.如果在第4步阻塞等待的時(shí)候,時(shí)間到了咬荷,那么返回false冠句,
    //否則,返回true幸乒。
    public final boolean await(long time, TimeUnit unit)
            throws InterruptedException {
        long nanosTimeout = unit.toNanos(time);
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        final long deadline = System.nanoTime() + nanosTimeout;
        boolean timedout = false;
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            if (nanosTimeout <= 0L) {
                timedout = transferAfterCancelledWait(node);
                break;
            }
            if (nanosTimeout >= spinForTimeoutThreshold)
                LockSupport.parkNanos(this, nanosTimeout);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
            nanosTimeout = deadline - System.nanoTime();
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
        return !timedout;
    }

嘻嘻轩端,如果文章有錯誤的地方,麻煩小哥哥小姐姐幫忙指出改正逝变,一起學(xué)習(xí)基茵,一起交流。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末壳影,一起剝皮案震驚了整個(gè)濱河市拱层,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宴咧,老刑警劉巖根灯,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異掺栅,居然都是意外死亡烙肺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門氧卧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來桃笙,“玉大人,你說我怎么就攤上這事沙绝〔鳎” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵闪檬,是天一觀的道長星著。 經(jīng)常有香客問我,道長粗悯,這世上最難降的妖魔是什么虚循? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮样傍,結(jié)果婚禮上横缔,老公的妹妹穿的比我還像新娘。我一直安慰自己铭乾,他們只是感情好剪廉,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著炕檩,像睡著了一般斗蒋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上笛质,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天泉沾,我揣著相機(jī)與錄音,去河邊找鬼妇押。 笑死跷究,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的敲霍。 我是一名探鬼主播俊马,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼丁存,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了柴我?” 一聲冷哼從身側(cè)響起解寝,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎艘儒,沒想到半個(gè)月后聋伦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡界睁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年觉增,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翻斟。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逾礁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出杨赤,到底是詐尸還是另有隱情敞斋,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布疾牲,位于F島的核電站植捎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏阳柔。R本人自食惡果不足惜焰枢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望舌剂。 院中可真熱鬧济锄,春花似錦、人聲如沸霍转。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽避消。三九已至低滩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間岩喷,已是汗流浹背恕沫。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纱意,地道東北人婶溯。 一個(gè)月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親迄委。 傳聞我的和親對象是個(gè)殘疾皇子褐筛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容