CyclicBarrier
1. 前言
- 同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点
- 计数器可重置后使用
- CyclicBarrier 和 CountDownLatch的区别:
CountDownLatch | CyclicBarrier |
---|---|
减计数方式 | 加计数方式 |
计算为0时释放所有等待的线程 | 计数达到指定值时释放所有等待线程 |
计数为0时,无法重置 | 计数达到指定值时,计数置为0重新开始 |
调用countDown()方法计数减一,调用await()方法只进行阻塞,对计数没任何影响 | 调用await()方法计数加1,若加1后的值不等于构造方法的值,则线程阻塞 |
不可重复利用 | 可重复利用 |
2. 源码解析
2.1 数据结构
CyclicBarrier 包含 ReentrantLock对象Lock和Condition对象trip,由独占锁ReentrantLock实现。
2.2 成员变量
1 | private final ReentrantLock lock = new ReentrantLock(); |
2.3 核心方法
- CyclicBarrier()构造方法
1 | public CyclicBarrier(int parties) { |
- await()
1 | public int await() throws InterruptedException, BrokenBarrierException { |
await()在dowait()中实现
1 | //timed - 是否设置超时时间 |
1 | //更新换代,唤醒所有等待的线程 |
dowait() 流程:
- 如果当前线程被中断,即Thread.interrupted()为true;则通过breakBarrier()终止CyclicBarrier
- 将count -1,判断是否有parties个线程到达Barrier;如果没到达,线程进行等待,直到“有parties个线程到达barrier” 或 “当前线程被中断” 或 “超时”这3者之一发生, 当前线程才继续执行
- 如果所有线程都达到Barrier,有设置barrierCommand,则执行barrierCommand,然后唤醒所有等待的线程,更新generation