什么是CountDownLatch
CountDownLatch
为一个多线程协调辅助工具。一句话描述是当n个线程都进行完工作之后,再通知另一组已阻塞的线程恢复执行。
使用方法
CountDownLatch
的构造函数中需要指定参数n。
CountDownLatch latch = new CountDownLatch(n);
需要等待其他线程工作的线程需要调用:
latch.await();
工作线程任务执行完之后调用:
latch.countDown();
一旦countDown
方法累计调用满n次,所有阻塞在await
方法的线程会恢复执行。
注意:CountDownLatch
的计数n是无法重置的。一旦创建完成只能通过countDown
方法递减。如果需要重新设置n值,需要创建新的CountDownLatch
。
countDown方法的实现
和ReentrantLock
一样,CountDownLatch
内部也有一个Sync
,继承自AQS。
CountDownLatch
基于共享锁的方式来实现,这个在后面介绍。
countDown
方法调用的是释放共享锁的逻辑。代码如下:
public void countDown() {
sync.releaseShared(1);
}
await方法
await
方法调用的是获取共享锁的逻辑,代码如下:
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
Sync类
CountDownLatch
的重点逻辑位于Sync
类中。
和ReentrantLock
不同,CountDownLatch
的Sync
初始化时候的state已经被设置为n。接下来每次调用countDown
的时候通过CAS将state减去1。所有调用await
的线程会对比state的值,只有state为0的时候,才允许执行,否则一律阻塞。
Sync
类的代码和相关解释如下所示:
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
// 创建CountDownLatch时候设置初始的state值
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
// await方法调用。await方法获取共享锁
// 如果state状态为0,说明有state个线程执行了countDown方法,此时唤醒所有的await线程
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
// countDown方法调用,释放共享锁
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
// 自旋
for (;;) {
int c = getState();
// 如果已经有state个线程执行过countDown,返回false
if (c == 0)
return false;
// state减一
int nextc = c-1;
// CAS设置state
// 只有nextc为0的时候返回true,唤醒await阻塞的线程
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
本文为原创内容,欢迎大家讨论、批评指正与转载。转载时请注明出处。