AQS源码浅析(9)——CountDownLatch
2022-04-27 本文已影响0人
墨_0b54
CountDownLatch是共享锁的一种实现, 它默认构造 AQS 的 state 值为 count,允许n(int最大值)个线程阻塞在一个地方,直至所有线程的任务都执行完毕。
- 当调用 await方法的时候,如果 state 不为 0,那就证明任务还没有执行完毕,await() 方法就会一直阻塞。
- 当线程使用 countDown方法时,其实使用了tryReleaseShared方法来减少 state直到为 0 ,就会释放所有等待的线程。
- CountDownLatch是一次性的,看看源码实现,state不能被恢复
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
protected int tryAcquireShared(int acquires) { //state不为0时阻塞
return (getState() == 0) ? 1 : -1;
}
protected boolean tryReleaseShared(int releases) {//state不为0时减1
// 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 的两种典型用法
1、某一线程在开始运行前等待 n 个线程执行完毕。
将 CountDownLatch 的计数器初始化为 n (new CountDownLatch(n)),每当一个任务线程执行完毕,就将计数器减 1 (countdownlatch.countDown()),当计数器的值变为 0 时,在 CountDownLatch 上 await() 的线程就会被唤醒。一个典型应用场景就是启动一个服务时,主线程需要等待多个组件加载完毕,之后再继续执行。
2、实现多个线程开始执行任务的最大并行性。
注意是并行性,不是并发,强调的是多个线程在某一时刻同时开始执行。类似于赛跑,将多个线程放到起点,等待发令枪响,然后同时开跑。做法是初始化一个共享的 CountDownLatch 对象,将其计数器初始化为 1 (new CountDownLatch(1)),多个线程在开始执行任务前首先 coundownlatch.await(),当主线程调用 countDown() 时,计数器变为 0,多个线程同时被唤醒。