CountDownLatch源碼解析

CountDownLatch

CountDownLatch的同步隊列結構:
雙向鏈表,其中,head是空節點new Node(),tail是最後一個線程node

await()方法解析

 public void await() throws InterruptedException {
        //調用AQS的模板方法
        sync.acquireSharedInterruptibly(1);
 }

 /**
 AQS的模板方法
 */
 private void doAcquireSharedInterruptibly(int arg)
        throws InterruptedException {
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            for (;;) {
                //一個死循環,直到tryAcquireShared成功
                final Node p = node.predecessor();                    
                if (p == head) {
                    //前驅節點是head,嘗試獲取鎖
                    //tryAcquireShared()是AQS子類實現的
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                        //成功獲取,將node變成頭結點,循環退出的唯一條件
						//並喚醒後續節點的線程,使後續節點能夠自旋檢測,即此for循環
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        failed = false;
                        return;
                    }
                }
                //shouldParkAfterFailedAcquire如果前驅節點是signal則返回true,否則將前驅節點設置成signal
                //parkAndCheckInterrupt將線程掛起
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
}

/**
AQS子類即CountDownLatch內部類Sync實現的方法
*/
protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
}

 /*
   將線程node加入鏈表
 */
 private Node addWaiter(Node mode) {
    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) {
        //如果tail不是null說明已經有node加入到隊列
        //設置新加入的node的前驅是tail
        node.prev = pred;
        //新加入的node爲tail
        if (compareAndSetTail(pred, node)) {
            //讓node的前驅指向node
            pred.next = node;
            return node;
        }
    }
    //尚未有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
            node.prev = t;
            if (compareAndSetTail(t, node)) {
                t.next = node;
                return t;
            }
        }
    }
}

countDwon()方法解析

  public void countDown() {
        //減少1個state
        sync.releaseShared(1);
    }
  
/**
AQS的模板方法
*/
public final boolean releaseShared(int arg) {
    if (tryReleaseShared(arg)) {
        doReleaseShared();
        return true;
    }
    return false;
}
/**
Sync的釋放鎖方法
*/
protected boolean tryReleaseShared(int releases) {
    // Decrement count; signal when transition to zero
    for (;;) {
        int c = getState();
        if (c == 0)
            return false;
        int nextc = c-1;
        if (compareAndSetState(c, nextc))
            return nextc == 0;
    }
}
private void doReleaseShared() {
    for (;;) {
        //頭結點是new Node()  空的
        Node h = head;
        if (h != null && h != tail) {
            int ws = h.waitStatus;
            if (ws == Node.SIGNAL) {
                //頭結點是SIGNAL,說明需要喚醒其後續結點
                if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                    continue;            // loop to recheck cases
                //喚醒後續結點線程
                unparkSuccessor(h);
            }
            else if (ws == 0 &&
                     !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                continue;                // loop on failed CAS
        }
        if (h == head)                   // loop if head changed
            break;
    }
}
發佈了70 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章