并发

CountDownLatch 源码解析—— countDown()

上一篇文章从源码层面说了一下CountDownLatch中await()的原理。这篇文章说一下countDown()。public void countDown() { //CountDownLatch sync.releaseShared(1);} ↓public&

Java并发计数器三部曲

第一篇《Java并发中同步计数器-countdowlatch 和 cyclicbarrier 的内部原理和用法》

第二篇《CountDownLatch 源码解析—— await()》


第三篇《CountDownLatch 源码解析—— countDown()》

上一篇文章从源码层面说了一下CountDownLatch 中 await() 的原理。这篇文章说一下countDown() 。

public void countDown() { //CountDownLatch
    sync.releaseShared(1);
}
    ↓
public final boolean releaseShared(int arg) { //AQS
    if (tryReleaseShared(arg)) {
        doReleaseShared();
        return true;
    }
    return false;
}
    ↓
protected boolean tryReleaseShared(int releases) { //CountDownLatch.Sync 
    // 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;
    }
}

通过构造器 CountDownLatch end = new CountDownLatch(2);  state 被设置为2,所以c == 2,nextc = 2-1, 

然后通过下面这个CAS操作将state设置为1。

protected final boolean compareAndSetState(int expect, int update) {        
    // See below for intrinsics setup to support this
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

此时nextc还不为0,返回false。一直等到countDown()  方法被调用两次,state == 0,nextc ==0,此时返回true。

进入doReleaseShared()方法。

doReleaseShared();
    ↓
private void doReleaseShared() {
    /*
     * Ensure that a release propagates, even if there are other
     * in-progress acquires/releases.  This proceeds in the usual
     * way of trying to unparkSuccessor of head if it needs
     * signal. But if it does not, status is set to PROPAGATE to
     * ensure that upon release, propagation continues.
     * Additionally, we must loop in case a new node is added
     * while we are doing this. Also, unlike other uses of
     * unparkSuccessor, we need to know if CAS to reset status
     * fails, if so rechecking.
     */
    for (;;) {
        Node h = head;
        if (h != null && h != tail) {
            int ws = h.waitStatus;
            if (ws == Node.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;
    }
}

回顾一下此时的等待队列模型。

   +--------------------------+   prev           +------------------+

原创不易,完成人机校验,阅读全文

相关推荐