CountDownLatch
内部类Sync 继承自AQS
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
//初始化时用AQS的state做计数器
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
//只是判断了一下state是否为0
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
//tryReleaseShared cas 把state-1 当state为0时返回true,否则返回false
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;
//如果当前tryReleaseShared把state变成0返回true,否则返回false
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
//当state!=0是执行doAcquireShared把线程加入到队列中
doAcquireShared(arg);
}
countDown方法
public void countDown() {
sync.releaseShared(1);
}
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
//如果释放得到0,才执行doReleaseShared方法
//逐渐释放队列中的所有值
doReleaseShared();
return true;
}
return false;
}
await方法
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
//响应中断
if (Thread.interrupted())
throw new InterruptedException();
//如果state不为0,doAcquireSharedInterruptibly把当前线程加入到阻塞队列中并阻塞 如果为0则不阻塞
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
//初始waitstatus状态为0,更新成-1后阻塞线程
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
return true;
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
总结
1.CountDownLatch内部有一个Sync继承自AQS,使用AQS的state属性作为计数器。 2.await方法调用tryAcquireShared,tryAcquireShared不会对AQS的属性做变更,只会返回state的属性是否大于0,如果不为0说明不能执行,加入到AQS的阻塞队列中,在队列中的线程会自旋执行tryAcquireShared,即判断是否为0,如果不是0则阻塞。 3.countDown()方法每次通过cas吧state减1,如果结果为0,唤醒队列中所有的线程