1、类注释摘抄
对于失败的同步尝试,CyclicBarrier 使用了一种要么全部要么全不 (all-or-none) 的破坏模式:如果因为中断、失败或者超时等原因,导致线程过早地离开了屏障点,那么在该屏障点等待的其他所有线程也将通过 BrokenBarrierException
(如果它们几乎同时被中断,则用 InterruptedException
)以反常的方式离开。
2、源码中的主要方法
/**
* Each use of the barrier is represented as a generation instance.
* The generation changes whenever the barrier is tripped, or
* is reset. There can be many generations associated with threads
* using the barrier - due to the non-deterministic way the lock
* may be allocated to waiting threads - but only one of these
* can be active at a time (the one to which {@code count} applies)
* and all the rest are either broken or tripped.
* There need not be an active generation if there has been a break
* but no subsequent reset.
*每个barrier都有一个Generation。当barrier被tripped或者重置时,Generation会变化
*使用barrier的线程会和许多Generation相关,因为不确定的方式,锁可能被分配给等待线程。
*但是每次只有一个在活动,其余的都会被破坏或者tripped。如果有中断但是没有后继重置,不需要激活新的一代
*/
private static class Generation {
boolean broken = false;
}
/** The lock for guarding barrier entry */
//barrier的入口锁
private final ReentrantLock lock = new ReentrantLock();
/** Condition to wait on until tripped */
//Condition等待tripped
private final Condition trip = lock.newCondition();
/** The number of parties */
//通过构造器传入的参数,表示总的等待线程的数量。
private final int parties;
/* The command to run when tripped */
//当屏障正常打开后运行的程序,通过最后一个调用await的线程来执行。
private final Runnable barrierCommand;
/** The current generation */
private Generation generation = new Generation();
/**
* Number of parties still waiting. Counts down from parties to 0
* on each generation. It is reset to parties on each new
* generation or when broken.
*还在等待的线程数量。每一代的Conuts都会从总的等待数量下降到0
每启动新的一代,或者broken时会重置为总等待数量。
*/
private int count;
/**
* Updates state on barrier trip and wakes up everyone.
* Called only while holding lock.
*当barrier trip的时候更新state。唤醒每一个
*只有当拥有锁的时候调用。
*/
private void nextGeneration() {
// signal completion of last generation
//通知上一代完成,
trip.signalAll();
// set up next generation设置新的一代。
count = parties;
generation = new Generation();
}
/**
* Sets current barrier generation as broken and wakes up everyone.
* Called only while holding lock.
*把当前barrier的一代设置为broken,唤醒每一个。
*拥有锁的时候调用。
*/
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}
/**
* Main barrier code, covering the various policies.
*主要的barrier代码,覆盖了各种策略
*/
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)//如果是broken状态,则抛出异常
throw new BrokenBarrierException();
if (Thread.interrupted()) {//如果线程是中断状态,则唤醒所有,generation的broken为true,抛出异常
breakBarrier();
throw new InterruptedException();
}
int index = --count;//减少当前count
if (index == 0) { // tripped如果count当前为0,则证明已经是trripped状态,运行之前输入的Runnable
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
nextGeneration();//通知所有线程,继续下一代的设置。
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
// loop until tripped, broken, interrupted, or timed out
//除非tripped,中断或者超时,否则循环
for (;;) {
try {
if (!timed)//如果没设置超时状态,则等待
trip.await();//await()会释放锁,这样下一个线程就可以继续dowait()
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.
Thread.currentThread().interrupt();
}
}
if (g.broken)
throw new BrokenBarrierException();
//因为别的线程是最后一个await的,也就是会调用nextGeneration();生成一个新的generation
//所以正常情况下g会不等于generation,执行返回index
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}