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 +------------------+
原创不易,完成人机校验,阅读全文