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 原理剖析

        共 24697字,需瀏覽 50分鐘

         ·

        2023-08-10 15:06

        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)爭(zhē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 都有用其作為同步器。

        推薦閱讀

        《synchronized 原理知多少》

        《Java 多線程中使用 JDK 自帶工具類實(shí)現(xiàn)計(jì)數(shù)器》

        《volatile 手摸手帶你解析》

        《Java 線程通信之 wait/notify 機(jī)制》

        《你必須會(huì)的 JDK 動(dòng)態(tài)代理和 CGLIB 動(dòng)態(tài)代理》


        關(guān)注【ytao】,更多原創(chuàng)好文



        瀏覽 353
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        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>
            久久精品久久久久 | 91人人人人 | 边添边摸边做边爱免费 | 亲女稚嫩撑到求饶蹂躏电影 | 三级-狂情欲事 | 做爱视频网站在线观看 | 沙奈朵狂揉下部羞羞动漫 | 水蜜桃隐私秘 视频免费 | 久久嫩草精品久久久久 | 全球色影院|