AbstractQueuedSynchronizer部分源碼解析

    /**
     * 加鎖
     */
    public final void acquire(int arg) {
        // 首先嚐試獲取,如果獲取成功直接退出;如果獲取失敗,即競爭鎖失敗,則創建Node,並添加到同步隊列尾部。
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
    
    private Node addWaiter(Node mode) {
        // 創建節點,mode此時爲null,表示下一個等待節點爲空
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }

    private Node enq(final Node node) {
        // 通過自旋操作,保證將當前節點設置到同步隊列尾部
        for (;;) {
            Node t = tail;
            if (t == null) { // Must initialize
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }
    
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                /* 前驅爲頭結點且嘗試獲取同步狀態成功,則將當前節點設置爲頭節點,原頭結點解勾;
                 並返回false,用於finally決定是否取消獲取同步狀態;
                 */
                if (p == head && tryAcquire(arg)) {
                    // 如果當前結點獲取同步狀態成功了,那麼將當前節點設置爲頭結點。
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                // 如果獲取同步狀態失敗,檢查是否需要阻塞線程
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
    
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        /* 
            0:初始化
            CANCELLED =  1 :線程等待超時或者被中斷了,需要從同步隊列中移走
            SIGNAL    = -1 :後續的節點等待狀態,當前節點,通知後面的節點去運行
            CONDITION = -2 :當前節點處於等待隊列
            PROPAGATE = -3 :共享,表示狀態要往後面的節點傳播
        */    
        // 獲取前驅的狀態碼
        int ws = pred.waitStatus;
        // 如果前驅狀態碼爲 SIGNAL,則返回true,表示當前線程需要阻塞
        if (ws == Node.SIGNAL)
            return true;
        // 如果前驅狀態碼>0,即前驅已經取消,則將同步隊列中從該節點起,所有狀態爲取消的前驅一律解勾
        if (ws > 0) {         
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            // 代碼運行到這裏,狀態一般只可能爲0、-2或者-3,此時將前驅狀態設置爲 SIGNAL
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
    }

    private final boolean parkAndCheckInterrupt() {
        // 阻塞當前線程,並返回是否被中斷的狀態,底層使用UNSAFE.park(false, 0L);public native void park(boolean var1, long var2);
        LockSupport.park(this);
        return Thread.interrupted();
    }

    /**
     * 釋放鎖
     */
    public final boolean release(int arg) {
        // 這裏是模板方法,由子類實現;如果狀態修改成功,則後續邏輯將釋放鎖
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

    private void unparkSuccessor(Node node) {
        int ws = node.waitStatus;
        if (ws < 0)
            compareAndSetWaitStatus(node, ws, 0);
        Node s = node.next;
        // s.waitStatus > 0,表明該結點已被取消
        if (s == null || s.waitStatus > 0) {
            s = null;
            // 從尾部開始找到離頭結點最近的一個非空結點,然後對該結點進行喚醒
            for (Node t = tail; t != null && t != node; t = t.prev)
                if (t.waitStatus <= 0)
                    s = t;
        }
        if (s != null)
            // 喚醒線程,底層由UNSAFE.unpark(thread)實現。public native void unpark(Object var1);
            LockSupport.unpark(s.thread);
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章