1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        AQS 原理剖析

        共 8469字,需瀏覽 17分鐘

         ·

        2020-08-29 10:59

        AQSAbstractQueuedSynchronizer類稱作隊列同步器,是構(gòu)建其他同步器的一個重要的基礎(chǔ)框架,同步器自身是沒有實(shí)現(xiàn)任何同步接口。它是通過控制一個int類型的state變量來表示同步狀態(tài),使用一個內(nèi)置的FIFO(先進(jìn)先出)隊列來構(gòu)建工作隊列操作。

        同步器定義有兩種資源共享方式:Exclusive(獨(dú)占式)和Share(共享式)的獲取同步狀態(tài)。

        獨(dú)占式:一個時間點(diǎn)只能執(zhí)行一個線程。共享式:一個時間點(diǎn)可多個線程同時執(zhí)行。

        使用方式

        同步器的設(shè)計采用模板模式,要實(shí)現(xiàn)一個同步組件得先繼承AbstractQueuedSynchronizer類,通過調(diào)用同步器提供的方法和重寫同步器的方法來實(shí)現(xiàn)。

        調(diào)用同步器中的方法就是調(diào)用前面提到的通過state變量值的操作來表示同步操作,state是被volatile修飾來保證線程可見性。

        方法名描述
        getState()獲取當(dāng)前線程同步狀態(tài)值。
        setState(int newState)設(shè)置當(dāng)前同步狀態(tài)值。
        compareAndSetState(int expect, int update)通過CAS設(shè)置state的值。

        為了避免被重寫,以上方法都被final修飾了。

        實(shí)現(xiàn)同步組件,需要自己根據(jù)自己定制化的需求進(jìn)行處理,所以需要自己重寫同步器提供的方法,要重寫的方法主要是獨(dú)占式獲取與釋放同步狀態(tài)、共享式獲取與釋放同步狀態(tài)。

        tryAcquire(int arg) 獨(dú)占式獲取同步狀態(tài),返回值為boolean類型,獲取成返回true,獲取失敗返回false

        tryRelease(int arg) 獨(dú)占式釋放同步狀態(tài),返回值為boolean類型,釋放成返回true,釋放失敗返回false。

        tryAcquireShared(int arg) 共享式獲取同步狀態(tài),返回值為int類型,獲取成功返回大于 0 的值。

        tryReleaseShared(int arg) 共享式釋放同步狀態(tài),返回值為boolean類型,釋放成返回true,釋放失敗返回false。

        isHeldExclusively() 獨(dú)占模式下是否被當(dāng)前前程獨(dú)占,返回值為boolean類型,已被當(dāng)前線程所獨(dú)占返回true,反之為false。

        同步器隊列

        一個同步器里面擁有一個同步隊列多個等待隊列

        同步隊列

        AbstractQueuedSynchronizer類中,有一個內(nèi)部類Node,通過該類構(gòu)造一個內(nèi)部的同步隊列,這是一個FIFO 雙向隊列。當(dāng)前運(yùn)行線程回去同步狀態(tài)時,如果獲取失敗,則將當(dāng)前線程信息創(chuàng)建一個Node追加到同步隊列尾部,然后阻塞當(dāng)前線程,直到隊列的上一個節(jié)點(diǎn)的同步狀態(tài)釋放,再喚醒當(dāng)前線程嘗試重新獲取同步狀態(tài)。這個重新獲取同步狀態(tài)操作的節(jié)點(diǎn),一定要是同步隊列中第一節(jié)點(diǎn)。

        Node 源碼如下:

        static?final?class?Node?{
        ????//?共享模式下等待的標(biāo)記
        ????static?final?Node?SHARED?=?new?Node();
        ????//?獨(dú)占模式下等待的標(biāo)記
        ????static?final?Node?EXCLUSIVE?=?null;

        ????/*
        ????*?等待狀態(tài)常量值,以下四個常量都是
        ????*/

        ????static?final?int?CANCELLED?=??1;
        ????
        ????static?final?int?SIGNAL????=?-1;
        ????
        ????static?final?int?CONDITION?=?-2;
        ????
        ????static?final?int?PROPAGATE?=?-3;

        ????//?等待狀態(tài)
        ????volatile?int?waitStatus;

        ????//?當(dāng)前節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)
        ????volatile?Node?prev;

        ????//?當(dāng)前節(jié)點(diǎn)的后繼節(jié)點(diǎn)
        ????volatile?Node?next;

        ????//?獲取同步狀態(tài)的線程(引用)
        ????volatile?Thread?thread;

        ????//?等待隊列中的后繼節(jié)點(diǎn)
        ????Node?nextWaiter;

        ????//?是否共享模式
        ????final?boolean?isShared()?{
        ????????return?nextWaiter?==?SHARED;
        ????}

        ????//?獲取前驅(qū)節(jié)點(diǎn)
        ????final?Node?predecessor()?throws?NullPointerException?{
        ????????Node?p?=?prev;
        ????????if?(p?==?null)
        ????????????throw?new?NullPointerException();
        ????????else
        ????????????return?p;
        ????}

        ????Node()?{????//?Used?to?establish?initial?head?or?SHARED?marker
        ????}

        ????Node(Thread?thread,?Node?mode)?{?????//?Used?by?addWaiter
        ????????this.nextWaiter?=?mode;
        ????????this.thread?=?thread;
        ????}

        ????Node(Thread?thread,?int?waitStatus)?{?//?Used?by?Condition
        ????????this.waitStatus?=?waitStatus;
        ????????this.thread?=?thread;
        ????}
        }

        通過以上代碼,可以看到節(jié)點(diǎn)中保存了節(jié)點(diǎn)模式、等待狀態(tài)、線程引用、前驅(qū)和后繼節(jié)點(diǎn),構(gòu)造節(jié)點(diǎn)。

        同步隊列中被阻塞的線程的等待狀態(tài)包含有四個常量值:CANCELLED、SIGNAL、CONDITION、PROPAGATE ,它們對應(yīng)的被阻塞原因如下:

        • CANCELLED 同步隊列中當(dāng)前節(jié)點(diǎn)的線程等待超時或被中斷,需要從同步隊列中取消等待。
        • SIGNAL 當(dāng)前節(jié)點(diǎn)釋放同步狀態(tài)或被取消后,通知后繼節(jié)點(diǎn)的線程運(yùn)行。
        • CONDITION 當(dāng)前節(jié)點(diǎn)在 Condition 上等待,當(dāng)其他線程對 Condition 調(diào)用了 signal() 方法后,該節(jié)點(diǎn)將添加到同步隊列中。
        • PROPAGATE 該狀態(tài)存在共享模式的首節(jié)點(diǎn)中,當(dāng)前節(jié)點(diǎn)喚醒后將傳播喚醒其他節(jié)點(diǎn)。

        同步器中持有同步隊列的首節(jié)點(diǎn)和尾節(jié)點(diǎn)的引用,在AbstractQueuedSynchronizer中分別對應(yīng)headtail字段。

        所以同步隊列的基本結(jié)構(gòu)如圖:

        等待隊列

        AbstractQueuedSynchronizer類中包含一個內(nèi)部類ConditionObject,該類實(shí)現(xiàn)了Condition的接口。一個Condition對象包含一個等待隊列,同時Condition對象可以實(shí)現(xiàn)等待/通知功能。

        Condition持有等待隊列中的首節(jié)點(diǎn)(firstWaiter)和尾節(jié)點(diǎn)(lastWaiter),如下圖代碼所示:

        如果當(dāng)前線程調(diào)用Condition.await()時,會將當(dāng)前線程信息構(gòu)建一個 Node 節(jié)點(diǎn),因?yàn)?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">Condition持有等待隊列中的首尾節(jié)點(diǎn),所以將當(dāng)前等待隊列中的尾節(jié)點(diǎn)的nextWaiter指向當(dāng)前線程構(gòu)建的節(jié)點(diǎn),同時更新lastWaiter的引用節(jié)點(diǎn)。

        上述過程中的節(jié)點(diǎn)、隊列的操作,是獲取到鎖的線程來調(diào)用Condition.await()的,所以整個執(zhí)行過程在沒有基于 CAS 的情況下,也是線程安全的。

        通過以上的描述,可以知道一個同步器中同步隊列、等待隊列構(gòu)成的示意圖:

        當(dāng)調(diào)用Condition.await()時,同步隊列中的首節(jié)點(diǎn),也就是當(dāng)前線程所創(chuàng)建的節(jié)點(diǎn),會加入到等待隊列中的尾部,釋放當(dāng)前線程的同步狀態(tài)并且喚醒同步隊列的后繼節(jié)點(diǎn),當(dāng)前線程也就進(jìn)入等待狀態(tài),這個先后順序不能顛倒。這個過程相當(dāng)于同步隊列的首節(jié)點(diǎn)的線程構(gòu)造新的節(jié)點(diǎn)加入到等待隊列的尾部。

        當(dāng)調(diào)用Condition.signal()方法時,會先將等待隊列中首節(jié)點(diǎn)轉(zhuǎn)移到同步隊列尾部,然后喚醒該同步隊列中的線程,該線程從Condition.await()中自旋退出,接著在在同步器的acquireQueued()中自旋獲取同步狀態(tài)。

        當(dāng)調(diào)用Condition.wait()方法,同步隊列首節(jié)點(diǎn)轉(zhuǎn)移到等待隊列方法:

        public?final?void?await()?throws?InterruptedException?{
        ????//?如果線程已中斷,則拋出中斷異常
        ????if?(Thread.interrupted())
        ????????throw?new?InterruptedException();
        ????//?添加節(jié)點(diǎn)到等待隊列中
        ????Node?node?=?addConditionWaiter();
        ????//?修改?state?來達(dá)到釋放同步狀態(tài),避免死鎖
        ????int?savedState?=?fullyRelease(node);
        ????
        ????int?interruptMode?=?0;
        ????//?判斷當(dāng)前節(jié)點(diǎn)是否在同步隊列中
        ????while?(!isOnSyncQueue(node))?{
        ????????LockSupport.park(this);
        ????????if?((interruptMode?=?checkInterruptWhileWaiting(node))?!=?0)
        ????????????break;
        ????}
        ????//?繼續(xù)獲取同步狀態(tài)競爭
        ????if?(acquireQueued(node,?savedState)?&&?interruptMode?!=?THROW_IE)
        ????????interruptMode?=?REINTERRUPT;
        ????if?(node.nextWaiter?!=?null)?//?清除已取消的節(jié)點(diǎn)
        ????????unlinkCancelledWaiters();
        ????if?(interruptMode?!=?0)?//?被中斷時的處理
        ????????reportInterruptAfterWait(interruptMode);
        }

        上面addc方法是向等待隊列中添加一個新的節(jié)點(diǎn)。

        private?Node?addConditionWaiter()?{
        ????//?獲取等待隊列中尾節(jié)點(diǎn)
        ????Node?t?=?lastWaiter;
        ????//?如果最后一個節(jié)點(diǎn)已取消,則清除取消節(jié)點(diǎn)
        ????if?(t?!=?null?&&?t.waitStatus?!=?Node.CONDITION)?{
        ????????unlinkCancelledWaiters();
        ????????t?=?lastWaiter;
        ????}
        ????//?利用當(dāng)前線程信息創(chuàng)建等待隊列的節(jié)點(diǎn)
        ????Node?node?=?new?Node(Thread.currentThread(),?Node.CONDITION);
        ????
        ????if?(t?==?null)?//?如果最后尾節(jié)點(diǎn)為空,當(dāng)前節(jié)點(diǎn)則為等待隊列的首節(jié)點(diǎn)
        ????????firstWaiter?=?node;
        ????else?//?否則將當(dāng)前尾節(jié)點(diǎn)的下一個節(jié)點(diǎn)指向當(dāng)前線程信息所構(gòu)造的節(jié)點(diǎn)
        ????????t.nextWaiter?=?node;
        ????lastWaiter?=?node;??//?更新?Condition?的尾節(jié)點(diǎn)引用
        ????return?node;
        }

        當(dāng)調(diào)用Condition.signal()方法,等待隊列首節(jié)點(diǎn)轉(zhuǎn)移到同步隊列方法:

        public?final?void?signal()?{
        ????//?是否被當(dāng)前線程所獨(dú)占
        ????if?(!isHeldExclusively())
        ????????throw?new?IllegalMonitorStateException();
        ????//?獲取等待隊列中首節(jié)點(diǎn)
        ????Node?first?=?firstWaiter;
        ????if?(first?!=?null)
        ????????//?轉(zhuǎn)移到同步隊列,然后喚醒該節(jié)點(diǎn)
        ????????doSignal(first);
        }

        轉(zhuǎn)移同步隊列首節(jié)點(diǎn)到同步隊列,并喚醒該節(jié)點(diǎn)方法doSignal()

        private?void?doSignal(Node?first)?{
        ????do?{
        ??????if?(?(firstWaiter?=?first.nextWaiter)?==?null)
        ??????????lastWaiter?=?null;
        ??????????//?去除首節(jié)點(diǎn)
        ??????????first.nextWaiter?=?null;
        ????}?while?(!transferForSignal(first)?&&?//?從等待隊列中轉(zhuǎn)移到同步隊列
        ??????????????(first?=?firstWaiter)?!=?null);
        }

        轉(zhuǎn)移等待隊列到同步隊列方法transferForSignal(Node node)

        final?boolean?transferForSignal(Node?node)?{
        ????//?驗(yàn)證節(jié)點(diǎn)是否被取消
        ????if?(!compareAndSetWaitStatus(node,?Node.CONDITION,?0))
        ????????return?false;
        ????//?轉(zhuǎn)移節(jié)點(diǎn)至同步隊列
        ????Node?p?=?enq(node);
        ????int?ws?=?p.waitStatus;
        ????if?(ws?>?0?||?!compareAndSetWaitStatus(p,?ws,?Node.SIGNAL))
        ????????LockSupport.unpark(node.thread);
        ????return?true;
        }

        等待隊列中的頭結(jié)點(diǎn)線程安全移動到同步隊列方法enq(final Node node)

        private?Node?enq(final?Node?node)?{
        ????for?(;;)?{
        ????????Node?t?=?tail;
        ????????//?同步隊列中如果為空,則初始化同步器
        ????????if?(t?==?null)?{?
        ????????????if?(compareAndSetHead(new?Node()))
        ????????????????tail?=?head;
        ????????}?else?{
        ????????????//?否則新節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)為當(dāng)前同步隊列的尾節(jié)點(diǎn)
        ????????????node.prev?=?t;
        ????????????//?設(shè)置當(dāng)前新節(jié)點(diǎn)為同步隊列的尾節(jié)點(diǎn),并更新先前同步隊列的尾節(jié)點(diǎn)的后繼節(jié)點(diǎn)指向當(dāng)前新節(jié)點(diǎn)
        ????????????if?(compareAndSetTail(t,?node))?{
        ????????????????t.next?=?node;
        ????????????????return?t;
        ????????????}
        ????????}
        ????}
        }

        獨(dú)占式同步狀態(tài)

        獨(dú)占式同步狀態(tài)獲取和釋放是線程安全的操作,一個時間點(diǎn)確保只有一個線程獲取到同步狀態(tài)。

        獨(dú)占式同步狀態(tài)獲取

        acquire(int arg)方法是獲取獨(dú)占式同步狀態(tài)的方法,當(dāng)線程獲取同步失敗時,會加入到同步隊列中。

        public?final?void?acquire(int?arg)?{
        ????if?(!tryAcquire(arg)?&&
        ????????acquireQueued(addWaiter(Node.EXCLUSIVE),?arg))
        ????????selfInterrupt();
        }

        上述代碼中,當(dāng)執(zhí)行tryAcquire(int arg)方法獲取同步狀態(tài)失敗時,接著通過addWaiter(Node.EXCLUSIVE)構(gòu)造當(dāng)前線程信息的節(jié)點(diǎn),隨后將新構(gòu)造的節(jié)點(diǎn)通過acquireQueued(final Node node, int arg)方法加入到同步隊列中,節(jié)點(diǎn)在同步隊列中自旋等待獲取同步狀態(tài)。

        tryAcquire(int arg)是自定義同步器實(shí)現(xiàn)的,實(shí)現(xiàn)該方法需要保證線程安全獲取同步狀態(tài),前面講到AQS提供的compareAndSetState(int expect, int update)方法通過CAS設(shè)置state值來保證線程安全。

        上面獲取獨(dú)占式同步狀態(tài)時,主要分析acquireQueued(final Node node, int arg)方法,節(jié)點(diǎn)加入隊列并自旋等待。

        final?boolean?acquireQueued(final?Node?node,?int?arg)?{
        ????boolean?failed?=?true;
        ????try?{
        ????????//?是否中斷標(biāo)識
        ????????boolean?interrupted?=?false;
        ????????for?(;;)?{
        ????????????//?獲取當(dāng)前節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)
        ????????????final?Node?p?=?node.predecessor();
        ????????????//?如果前驅(qū)節(jié)點(diǎn)是首節(jié)點(diǎn),并且當(dāng)前節(jié)點(diǎn)獲取到同步狀態(tài)
        ????????????if?(p?==?head?&&?tryAcquire(arg))?{
        ????????????????//?將當(dāng)前節(jié)點(diǎn)設(shè)置為首節(jié)點(diǎn)
        ????????????????setHead(node);
        ????????????????//?將原首節(jié)點(diǎn)(即當(dāng)前節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn))引用清空,利于 GC 回收
        ????????????????p.next?=?null;
        ????????????????//?成功獲取到同步狀態(tài)標(biāo)志
        ????????????????failed?=?false;
        ????????????????return?interrupted;
        ????????????}
        ????????????//?判斷前驅(qū)節(jié)點(diǎn)是否超時或取消,以及當(dāng)前線程是否被中斷
        ????????????if?(shouldParkAfterFailedAcquire(p,?node)?&&
        ????????????????parkAndCheckInterrupt())
        ????????????????interrupted?=?true;
        ????????}
        ????}?finally?{
        ????????//?如果被中斷,則節(jié)點(diǎn)出隊
        ????????if?(failed)
        ????????????cancelAcquire(node);
        ????}
        }

        在首節(jié)點(diǎn)釋放同步狀態(tài)后,同時喚醒后繼節(jié)點(diǎn)。后繼節(jié)點(diǎn)通過自旋的方式(這里利用死循環(huán)方式)也會檢查自己的前驅(qū)節(jié)點(diǎn)是否為首節(jié)點(diǎn),如果是前驅(qū)節(jié)點(diǎn)則會嘗試獲取同步狀態(tài)。獲取成功則返回,否則判斷是否被中斷或者繼續(xù)自旋上述獲取同步狀態(tài)操作。

        獨(dú)占式同步狀態(tài)釋放

        release(int arg)方法是釋放同步狀態(tài),當(dāng)釋放同步狀態(tài)后會喚醒后繼節(jié)點(diǎn)。

        public?final?boolean?release(int?arg)?{
        ????if?(tryRelease(arg))?{
        ????????Node?h?=?head;
        ????????if?(h?!=?null?&&?h.waitStatus?!=?0)
        ????????????unparkSuccessor(h);
        ????????return?true;
        ????}
        ????return?false;
        }

        tryRelease(int arg)方法同樣也是自定義同步器實(shí)現(xiàn)。當(dāng)首節(jié)點(diǎn)不為空且處于等待狀態(tài)時,那么調(diào)用unparkSuccessor(Node node)方法喚醒后繼節(jié)點(diǎn)。

        private?void?unparkSuccessor(Node?node)?{
        ????//?CAS?設(shè)置等待狀態(tài)為初始狀態(tài)
        ????int?ws?=?node.waitStatus;
        ????if?(ws?0)
        ????????compareAndSetWaitStatus(node,?ws,?0);

        ????Node?s?=?node.next;
        ????//?如果當(dāng)前釋放同步狀態(tài)的節(jié)點(diǎn)不存在后繼節(jié)點(diǎn)或后繼節(jié)點(diǎn)超時/被中斷
        ????if?(s?==?null?||?s.waitStatus?>?0)?{
        ????????s?=?null;
        ????????//?從尾節(jié)點(diǎn)中開始尋找等待狀態(tài)的節(jié)點(diǎn)作為新首節(jié)點(diǎn),這里已排除當(dāng)前節(jié)點(diǎn)(t != node)
        ????????for?(Node?t?=?tail;?t?!=?null?&&?t?!=?node;?t?=?t.prev)
        ????????????if?(t.waitStatus?<=?0)
        ????????????????s?=?t;
        ????}
        ????if?(s?!=?null)
        ????????LockSupport.unpark(s.thread);
        }

        釋放同步狀態(tài)的整個過程就是:釋放同步狀態(tài),喚醒后繼節(jié)點(diǎn)。這個后繼節(jié)點(diǎn)必須滿足,非空、非當(dāng)前節(jié)點(diǎn)、等待狀態(tài)小于或等于 0 ,即SIGNALCONDITION、PROPAGATE和初始化狀態(tài)。

        獨(dú)占式資源共享方式除了上面的同步狀態(tài)獲取,還有獨(dú)占式超時獲取使用的方法是doAcquireNanos(int arg, long nanosTimeout)、獨(dú)占式可中斷獲取使用的方法是acquireInterruptibly(int arg)

        共享式同步狀態(tài)

        共享式同步狀態(tài)同一時間點(diǎn)可以有多個線程獲取到同步狀態(tài)。

        共享式同步狀態(tài)獲取

        acquireShared(int arg)方法是共享式同步狀態(tài)獲取的方法。

        public?final?void?acquireShared(int?arg)?{
        ????if?(tryAcquireShared(arg)?0)
        ????????//?獲取同步狀態(tài)失敗后調(diào)用的方法
        ????????doAcquireShared(arg);
        }

        tryAcquireShared(int arg)方法是自定義同步器實(shí)現(xiàn)的,返回大于或等于 0 時,表示獲取成功。如果小于 0 時,獲取同步狀態(tài)失敗后會調(diào)用doAcquireShared(int arg)方法進(jìn)行再次嘗試獲取。

        private?void?doAcquireShared(int?arg)?{、
        ????//?構(gòu)造一個當(dāng)前線程信息的新節(jié)點(diǎn)
        ????final?Node?node?=?addWaiter(Node.SHARED);
        ????boolean?failed?=?true;
        ????try?{
        ????????boolean?interrupted?=?false;
        ????????//?自旋式獲取同步狀態(tài)
        ????????for?(;;)?{
        ????????????final?Node?p?=?node.predecessor();
        ????????????//?判斷新節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)是否為首節(jié)點(diǎn)
        ????????????if?(p?==?head)?{
        ????????????????//?再次嘗試獲取同步狀態(tài)
        ????????????????int?r?=?tryAcquireShared(arg);
        ????????????????//?獲取成功后退出自旋
        ????????????????if?(r?>=?0)?{
        ????????????????????setHeadAndPropagate(node,?r);
        ????????????????????p.next?=?null;?//?help?GC
        ????????????????????if?(interrupted)
        ????????????????????????selfInterrupt();
        ????????????????????failed?=?false;
        ????????????????????return;
        ????????????????}
        ????????????}
        ????????????if?(shouldParkAfterFailedAcquire(p,?node)?&&
        ????????????????parkAndCheckInterrupt())
        ????????????????interrupted?=?true;
        ????????}
        ????}?finally?{
        ????????if?(failed)
        ????????????cancelAcquire(node);
        ????}
        }

        上面代碼中,當(dāng)獲取同步狀態(tài)失敗后,則創(chuàng)建一個共享模式類型的節(jié)點(diǎn),然后自旋式獲取同步狀態(tài),如果前驅(qū)節(jié)點(diǎn)為首節(jié)點(diǎn)時則嘗試再次獲取同步狀態(tài),獲取同步狀態(tài)成功后退出當(dāng)前自旋。

        共享式釋放同步狀態(tài)

        releaseShared(int arg)方法來釋放共享式同步狀態(tài)。

        public?final?boolean?releaseShared(int?arg)?{
        ????if?(tryReleaseShared(arg))?{
        ????????//?同步狀態(tài)釋放成功后,喚醒后面等待狀態(tài)的節(jié)點(diǎn)
        ????????doReleaseShared();
        ????????return?true;
        ????}
        ????return?false;
        }

        上面tryReleaseShared(int arg)釋放同步狀態(tài)方法必須保證線程安全,因?yàn)樗鄠€線程獲取到同步狀態(tài)時會引發(fā)并發(fā)操作,可以通過循環(huán)操作和 CAS 來確保安前行。

        doReleaseShared()方法喚醒后續(xù)等待狀態(tài)的節(jié)點(diǎn)。

        private?void?doReleaseShared()?{
        ????for?(;;)?{
        ????????Node?h?=?head;
        ????????if?(h?!=?null?&&?h?!=?tail)?{
        ????????????int?ws?=?h.waitStatus;
        ????????????//?驗(yàn)證后繼節(jié)點(diǎn)的線程處于等待狀態(tài)
        ????????????if?(ws?==?Node.SIGNAL)?{
        ????????????????//?再次檢查后繼節(jié)點(diǎn)的線程是否處于等待狀態(tài)
        ????????????????if?(!compareAndSetWaitStatus(h,?Node.SIGNAL,?0))
        ????????????????????continue;???
        ????????????????//?喚醒后繼節(jié)點(diǎn),這時每喚醒一次就更新一次首節(jié)點(diǎn)
        ????????????????unparkSuccessor(h);
        ????????????}
        ????????????else?if?(ws?==?0?&&
        ??????????????????????!compareAndSetWaitStatus(h,?0,?Node.PROPAGATE))
        ????????????????continue;????????????????//?loop?on?failed?CAS
        ????????}
        ????????if?(h?==?head)???????????????????//?loop?if?head?changed
        ????????????break;
        ????}
        }

        共享同步狀態(tài)釋放后,自旋式依次喚醒隊列中節(jié)點(diǎn)。

        總結(jié)

        從 AQS 中可以借鑒它利用循環(huán)和 CAS 來確保并發(fā)的安全性的思路,同時它采用模板設(shè)計模式定義一個處理邏輯,將具體的特定處理邏輯交由子類自定義實(shí)現(xiàn)。在 ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch 以及 Tomncat 的 LimitLatch 都有用其作為同步器。


        點(diǎn)個在看支持我吧,轉(zhuǎn)發(fā)就更好了
        瀏覽 47
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            五区无码 | 成人毛片免费播放 | 伊人激情四射 | 内射无套内射国产精品视频 | a在线观看视频 | 男男被狂c躁到高潮失禁网站 | 免费一级a毛一级a看免费视频下载 | 天干天干天夜夜 | www.av黄色电影.co m | 大奶无码 |