concurrent-5-AQS-Condition

等待

await

 public final void await() throws InterruptedException {
            if (Thread.interrupted())  //響應中斷
                throw new InterruptedException();
            Node node = addConditionWaiter();   //加入到條件隊列尾
            int savedState = fullyRelease(node);  //返回aqs狀態
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {   //查看當前節點是否在同步隊列中,等待signal後會入同步隊列
                LockSupport.park(this);   //不在同步隊列中需要睡眠
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)  //檢查是否有被中斷
                    break;
            }
            //嘗試從隊列中獲取資源
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null) // clean up if cancelled
                unlinkCancelledWaiters();  //清除非等待的節點
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);  //判斷中斷類型後進行相應的中斷處理
        }

addConditionWaiter

private Node addConditionWaiter() {
            Node t = lastWaiter;    //condition 隊列尾
            // If lastWaiter is cancelled, clean out.
            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;
        }

unlinkCancelledWaiters

 private void unlinkCancelledWaiters() {
            Node t = firstWaiter;  //獲取頭節點
            Node trail = null;    //臨時節點
            while (t != null) {
                Node next = t.nextWaiter;   //獲取下一節點
                if (t.waitStatus != Node.CONDITION) {   //如果當前節點不爲條件等待
                    t.nextWaiter = null;    //清除t help gc
                    if (trail == null)  //如果臨時節點爲null
                        firstWaiter = next;  //則next節點爲頭節點
                    else
                        trail.nextWaiter = next;  //將當前節點過濾掉,
                    if (next == null)    //當next爲null時,則表明到達了隊列尾
                        lastWaiter = trail;
                }
                else
                    trail = t;  //將當前節點記錄
                t = next;   //開始判斷下一個節點
            }
        }

fullyRelease

 final int fullyRelease(Node node) {
        boolean failed = true;
        try {
            int savedState = getState();   //獲取aqs狀態
            if (release(savedState)) {  //嘗試釋放鎖資源
                failed = false;
                return savedState;
            } else {
                throw new IllegalMonitorStateException();
            }
        } finally {
            if (failed)  //如果失敗報錯
                node.waitStatus = Node.CANCELLED;  //將節點標記爲取消
        }
    }

isOnSyncQueue

final boolean isOnSyncQueue(Node node) {
        if (node.waitStatus == Node.CONDITION || node.prev == null)
            return false;
        if (node.next != null) // If has successor, it must be on queue
            return true;
        /*
         * node.prev can be non-null, but not yet on queue because
         * the CAS to place it on queue can fail. So we have to
         * traverse from tail to make sure it actually made it.  It
         * will always be near the tail in calls to this method, and
         * unless the CAS failed (which is unlikely), it will be
         * there, so we hardly ever traverse much.
         */
        return findNodeFromTail(node);  //從尾部遍歷,如果不在隊列中則返回false
    }

喚醒

signal

public final void signal() {
            if (!isHeldExclusively())  //如果當前線程不是持有鎖的線程,則拋異常
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;
            if (first != null)
                doSignal(first);  //將隊列標記爲signal 併入syc隊列
        }

doSignal

private void doSignal(Node first) {
            do {
                if ( (firstWaiter = first.nextWaiter) == null)  //判斷條件隊列節點
                    lastWaiter = null;
                first.nextWaiter = null;
            } while (!transferForSignal(first) &&   //將條件隊列入同步同列
                     (first = firstWaiter) != null);
        }

transferForSignal

final boolean transferForSignal(Node node) {
        /*
         * If cannot change waitStatus, the node has been cancelled.
         */
        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
            return false;

        /*
         * Splice onto queue and try to set waitStatus of predecessor to
         * indicate that thread is (probably) waiting. If cancelled or
         * attempt to set waitStatus fails, wake up to resync (in which
         * case the waitStatus can be transiently and harmlessly wrong).
         */
        Node p = enq(node);  //入同步隊列
        int ws = p.waitStatus;
        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
            LockSupport.unpark(node.thread);
        return true;
    }

doSignalAll

  private void doSignalAll(Node first) {
            lastWaiter = firstWaiter = null;
            do {
                Node next = first.nextWaiter;
                first.nextWaiter = null;
                transferForSignal(first);  //一個個喚醒
                first = next;
            } while (first != null);
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章