<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          AQS 原理剖析

          共 8469字,需瀏覽 17分鐘

           ·

          2020-08-29 10:59

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

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

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

          使用方式

          同步器的設(shè)計(jì)采用模板模式,要實(shí)現(xiàn)一個(gè)同步組件得先繼承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。

          同步器隊(duì)列

          一個(gè)同步器里面擁有一個(gè)同步隊(duì)列多個(gè)等待隊(duì)列

          同步隊(duì)列

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

          ????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;

          ????//?等待隊(duì)列中的后繼節(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)。

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

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

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

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

          等待隊(duì)列

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

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

          如果當(dāng)前線程調(diào)用Condition.await()時(shí),會(huì)將當(dāng)前線程信息構(gòu)建一個(gè) 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持有等待隊(duì)列中的首尾節(jié)點(diǎn),所以將當(dāng)前等待隊(duì)列中的尾節(jié)點(diǎn)的nextWaiter指向當(dāng)前線程構(gòu)建的節(jié)點(diǎn),同時(shí)更新lastWaiter的引用節(jié)點(diǎn)。

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

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

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

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

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

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

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

          private?Node?addConditionWaiter()?{
          ????//?獲取等待隊(duì)列中尾節(jié)點(diǎn)
          ????Node?t?=?lastWaiter;
          ????//?如果最后一個(gè)節(jié)點(diǎn)已取消,則清除取消節(jié)點(diǎn)
          ????if?(t?!=?null?&&?t.waitStatus?!=?Node.CONDITION)?{
          ????????unlinkCancelledWaiters();
          ????????t?=?lastWaiter;
          ????}
          ????//?利用當(dāng)前線程信息創(chuàng)建等待隊(duì)列的節(jié)點(diǎn)
          ????Node?node?=?new?Node(Thread.currentThread(),?Node.CONDITION);
          ????
          ????if?(t?==?null)?//?如果最后尾節(jié)點(diǎn)為空,當(dāng)前節(jié)點(diǎn)則為等待隊(duì)列的首節(jié)點(diǎn)
          ????????firstWaiter?=?node;
          ????else?//?否則將當(dāng)前尾節(jié)點(diǎn)的下一個(gè)節(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()方法,等待隊(duì)列首節(jié)點(diǎn)轉(zhuǎn)移到同步隊(duì)列方法:

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

          轉(zhuǎn)移同步隊(duì)列首節(jié)點(diǎn)到同步隊(duì)列,并喚醒該節(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)?&&?//?從等待隊(duì)列中轉(zhuǎn)移到同步隊(duì)列
          ??????????????(first?=?firstWaiter)?!=?null);
          }

          轉(zhuǎn)移等待隊(duì)列到同步隊(duì)列方法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)至同步隊(duì)列
          ????Node?p?=?enq(node);
          ????int?ws?=?p.waitStatus;
          ????if?(ws?>?0?||?!compareAndSetWaitStatus(p,?ws,?Node.SIGNAL))
          ????????LockSupport.unpark(node.thread);
          ????return?true;
          }

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

          private?Node?enq(final?Node?node)?{
          ????for?(;;)?{
          ????????Node?t?=?tail;
          ????????//?同步隊(duì)列中如果為空,則初始化同步器
          ????????if?(t?==?null)?{?
          ????????????if?(compareAndSetHead(new?Node()))
          ????????????????tail?=?head;
          ????????}?else?{
          ????????????//?否則新節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)為當(dāng)前同步隊(duì)列的尾節(jié)點(diǎn)
          ????????????node.prev?=?t;
          ????????????//?設(shè)置當(dāng)前新節(jié)點(diǎn)為同步隊(duì)列的尾節(jié)點(diǎn),并更新先前同步隊(duì)列的尾節(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)獲取和釋放是線程安全的操作,一個(gè)時(shí)間點(diǎn)確保只有一個(gè)線程獲取到同步狀態(tài)。

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

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

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

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

          final?boolean?acquireQueued(final?Node?node,?int?arg)?{
          ????boolean?failed?=?true;
          ????try?{
          ????????//?是否中斷標(biāo)識(shí)
          ????????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)是否超時(shí)或取消,以及當(dāng)前線程是否被中斷
          ????????????if?(shouldParkAfterFailedAcquire(p,?node)?&&
          ????????????????parkAndCheckInterrupt())
          ????????????????interrupted?=?true;
          ????????}
          ????}?finally?{
          ????????//?如果被中斷,則節(jié)點(diǎn)出隊(duì)
          ????????if?(failed)
          ????????????cancelAcquire(node);
          ????}
          }

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

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

          release(int arg)方法是釋放同步狀態(tài),當(dāng)釋放同步狀態(tài)后會(huì)喚醒后繼節(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)時(shí),那么調(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)超時(shí)/被中斷
          ????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)的整個(gè)過程就是:釋放同步狀態(tài),喚醒后繼節(jié)點(diǎn)。這個(gè)后繼節(jié)點(diǎn)必須滿足,非空、非當(dāng)前節(jié)點(diǎn)、等待狀態(tài)小于或等于 0 ,即SIGNAL、CONDITIONPROPAGATE和初始化狀態(tài)。

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

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

          共享式同步狀態(tài)同一時(shí)間點(diǎn)可以有多個(gè)線程獲取到同步狀態(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 時(shí),表示獲取成功。如果小于 0 時(shí),獲取同步狀態(tài)失敗后會(huì)調(diào)用doAcquireShared(int arg)方法進(jìn)行再次嘗試獲取。

          private?void?doAcquireShared(int?arg)?{、
          ????//?構(gòu)造一個(gè)當(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)建一個(gè)共享模式類型的節(jié)點(diǎn),然后自旋式獲取同步狀態(tài),如果前驅(qū)節(jié)點(diǎn)為首節(jié)點(diǎn)時(shí)則嘗試再次獲取同步狀態(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)樗鄠€(gè)線程獲取到同步狀態(tài)時(shí)會(huì)引發(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),這時(shí)每喚醒一次就更新一次首節(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)釋放后,自旋式依次喚醒隊(duì)列中節(jié)點(diǎn)。

          總結(jié)

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


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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  性交免费网站 | 黄色电影在线观看网站 | 中日韩在线播放 | 激情色五月婷婷 | 最新国产精品视频豆花 |