通过AQS的互斥锁机制(ReentrantLock)+条件(Condition)实现的,用于一组线程相互之间等待,直到到达某个公共屏障点 (common barrier point),再继续执行。常用于多线程计算数据,当所有线程都完成执行后,在CyclicBarrier回调线程中合并计算。为方便源码解释,假定将一组线程表示为组
public class CyclicBarrier {
//Generation类在每组创建时都会生成一个该类的新的实例,用于下一组线程/reset方法后的复用,并恢复broken值
private static class Generation {
boolean broken = false; // 当前组有没有被强制中断
}
private final ReentrantLock lock = new ReentrantLock();
//用于阻塞线程的条件变量,有未到组的线程,那么在该条件变量上等待,进入AQS条件队列
private final Condition trip = lock.newCondition();
//参与组的线程数
private final int parties;
//当所有的线程都参与到了组中后回调的方法
private final Runnable barrierCommand;
//代表当前组
private Generation generation = new Generation();
//还未到组的线程数
private int count;
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
}
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe);
}
}
private int dowait(boolean timed, long nanos) throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
final Generation g = generation; //保存当前组的Generation快照,避免后面步骤的更新影响到这里的实例
if (g.broken)
throw new BrokenBarrierException();
//组中有中断的线程,干掉组内其他线程并重新开始,此时并没有改变组中的Generation
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
int index = --count;
if (index == 0) { //最后一个到达组的线程,回调barrierCommand(若正常完成,那么不需要手动调用reset,因为这里调用了nextGeneration),然后唤醒所有阻塞在条件变量上的线程
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run(); //执行回调
ranAction = true;
nextGeneration(); // 进入下一个组
return 0;
} finally {
// barrierCommand回调方法发生了异常,那么设置broken标志位
if (!ranAction)
breakBarrier();
}
}
// 循环等待最后一个进入组的线程唤醒自己,或者被中断、或者等待超时。
for (;;) {
try {
if (!timed)
trip.await();
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
} else {
Thread.currentThread().interrupt();
}
}
if (g.broken)
throw new BrokenBarrierException();
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); // 将所有组内线程唤醒
nextGeneration(); // 生成下一代
} finally {
lock.unlock();
}
}
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}
private void nextGeneration() {
trip.signalAll();
count = parties;
generation = new Generation(); // 生成了下一代组的实例
}