功能
- CyclicBarrier
- 调用 await 方法休眠线程,当所有线程都执行到达 await 点时,唤醒所有线程然后才执行后续代码
- 唤醒所有线程后,CyclicBarrier 进入下一个周期
意味着可以重复使用
- CountDownLatch
- 调用 await 休眠线程,当调用指定次数 countDown 后唤醒所有 await 的线程
- 执行了唤醒所有线程后,await 方法就会失效
意味着不可以重复使用
CyclicBarrier 可以重复使用的原因
- 关键代码
->await->dowait->nextGeneration
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
final Generation g = generation;
if (g.broken)
throw new BrokenBarrierException();
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
int index = --count;
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
......
}
------------------------------------------------
private void nextGeneration() {
// signal completion of last generation
trip.signalAll();
// set up next generation
count = parties;
generation = new Generation();
}
- 最终会执行
nextGeneration
方法- 该方法会唤醒所有的休眠线程
- 然后又把 count 重置为初始值
count值用来计数休眠的线程,当count为0时表示该唤醒所有线程了
CountDownLatch
Syn
CountDownLatch 使用的 AQS,主要定义了一个内部类 Sync
实现 AQS
因为 CountDownLatch 是共享锁,所以 Sync 重载的 tryAcquireShared
和 tryReleaseShared
当初始化 CountDownLatch 时需要指定数量,最后这个数量会被 Syn
使用,作为 AQS 的 state
流程
- 当调用 await 方法时,会生成节点插入到 AQS 的同步队列中然后使用 LockSupport 挂起线程
- 使用 countDown 方法时会调用 Syn 的 tryReleaseShared 方法将 state 的值减一,当 state 被减为 0 时,AQS 会调用 doReleaseShared 唤醒所有的线程
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于