java这个类上已经写了:一种同步辅助工具,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。
其示例在类的注释上已经有很完整的。
基于AQS实现了共享锁的方法。所以CountDownLatch可以看成多个线程同时获取指定的资源count,按照类的设计含义,等待所有线程都操作完成,同时唤醒向下执行。那么就是当AQS中的state减为0时,标志着所有线程完成。
private final Sync sync;
private static final class Sync extends AbstractQueuedSynchronizer {
//...下面有详细解释
}
private final Sync sync;
首先如果对AQS不熟悉,请先看AQS的相关知识java 并发编程系列文章目录
//让state - 1
public void countDown() {
sync.releaseShared(1);
}
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
// c == 0代表已经有线程cas设置成0了 所以就不需要去unpark线程了
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
//此时state变成0 那么去唤醒线程,那些线程因为await()方法阻塞着的
return nextc == 0;
}
}
await方法是用来阻塞当前线程的,如果当前state 不是等于0的就会阻塞,
//此时如果acquireShared state不是0 tryAcquireShared会返回-1 所以会添加shard的node到阻塞队列
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
//如果此时state != 0 那么会进行获取资源的操作 最后一个资源线程countDown时 此时自身线程是不会阻塞的,且countDown时执行
//AQS的ReleaseShared方法,会去把阻塞队列里的shard的node全部unpark。doReleaseShared会从Head一个一个park
//此时getState不是一个线程安全的方法,那么也不会造成影响,因为最后一个线程会countDown 唤醒所有线程之后同步调用await
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
CountDownLatch 利用了AQS的共享锁队列实现了线程同步等待操作全部完成后执行下步操作。 到达指定点的线程countDown让共享资源state -1,await方法会阻塞住当前线程,只有当countDown把state变成0时会ReleaseShared唤醒队列中的线程。