此文所涉及的源码及JavaDoc都是基于jdk8
/**
* A synchronization aid that allows a set of threads to all wait for
* each other to reach a common barrier point. CyclicBarriers are
* useful in programs involving a fixed sized party of threads that
* must occasionally wait for each other. The barrier is called
* <em>cyclic</em> because it can be re-used after the waiting threads
* are released.
* 一种同步辅助工具,允许一组线程彼此等待到达一个共同的barrier point。在含有固定数量
* 线程(有时这些线程需要彼此等待)的程序中CyclicBarrier非常有用。这个barrier是可循环的。
* 因为它能使处于waiting状态的线程被释放后可以重新被使用。
* <p>A {@code CyclicBarrier} supports an optional {@link Runnable} command
* that is run once per barrier point, after the last thread in the party
* arrives, but before any threads are released.
* This <em>barrier action</em> is useful
* for updating shared-state before any of the parties continue.
* CyclicBarrier支持一个可选的Runnable命令,该命令在每一个barrier point上运行一次,
* 运行的时机在最后一个线程到达之后,但是在释放任何线程之前。
* 这个barrier action对于在任何一方继续之前更新共享状态非常有用。
* <p><b>Sample usage:</b> Here is an example of using a barrier in a
* parallel decomposition design:
* 示例用法:下面是一个在并行分解设计中使用barrier的示例
* <pre> {@code
* class Solver {
* final int N;
* final float[][] data;
* final CyclicBarrier barrier;
*
* class Worker implements Runnable {
* int myRow;
* Worker(int row) { myRow = row; }
* public void run() {
* while (!done()) {
* processRow(myRow);
*
* try {
* barrier.await();
* } catch (InterruptedException ex) {
* return;
* } catch (BrokenBarrierException ex) {
* return;
* }
* }
* }
* }
*
* public Solver(float[][] matrix) {
* data = matrix;
* N = matrix.length;
* Runnable barrierAction =
* new Runnable() { public void run() { mergeRows(...); }};
* barrier = new CyclicBarrier(N, barrierAction);
*
* List<Thread> threads = new ArrayList<Thread>(N);
* for (int i = 0; i < N; i++) {
* Thread thread = new Thread(new Worker(i));
* threads.add(thread);
* thread.start();
* }
*
* // wait until done
* for (Thread thread : threads)
* thread.join();
* }
* }}</pre>
*
* Here, each worker thread processes a row of the matrix then waits at the
* barrier until all rows have been processed. When all rows are processed
* the supplied {@link Runnable} barrier action is executed and merges the
* rows. If the merger
* determines that a solution has been found then {@code done()} will return
* {@code true} and each worker will terminate.
* 在这里,每个worker线程处理矩阵的一行,然后在barrier处wait,直到所有的行都被处理完。
* 当处理完所有的行时,所定义的Runnable barrier action将被执行,合并所有的行。
* 如果合并确定找到了一个解决方案,done方法将返回true并且每个worker将终止。
* <p>If the barrier action does not rely on the parties being suspended when
* it is executed, then any of the threads in the party could execute that
* action when it is released. To facilitate this, each invocation of
* {@link #await} returns the arrival index of that thread at the barrier.
* You can then choose which thread should execute the barrier action, for
* example:
* <pre> {@code
* if (barrier.await() == 0) {
* // log the completion of this iteration
* }}</pre>
* 如果barrier action在执行时不依赖于被中止的各方,那么当它被释放时,参与方中的任何线程都可以执行该action。
* 方便起见,每次调用await都会返回该线程在barrier处的到达索引。此时你可以选择哪个线程执行barrier action。
* <p>The {@code CyclicBarrier} uses an all-or-none breakage model
* for failed synchronization attempts: If a thread leaves a barrier
* point prematurely because of interruption, failure, or timeout, all
* other threads waiting at that barrier point will also leave
* abnormally via {@link BrokenBarrierException} (or
* {@link InterruptedException} if they too were interrupted at about
* the same time).
* CyclicBarrier为失败的同步尝试使用一个all-or-none中断模型:如果一个线程由于中断、失败或超时
* 而提前离开一个barrier point,那么在该barrier point等待的所有其他线程也会通过抛出BrokenBarrierException异常。
* (或者InterruptedException,如果这些线程也同时被打断)。
* <p>Memory consistency effects: Actions in a thread prior to calling
* {@code await()}
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
* actions that are part of the barrier action, which in turn
* <i>happen-before</i> actions following a successful return from the
* corresponding {@code await()} in other threads.
* 内存一致性效应:在调用await方法之前线程中的操作happen-before barrier action中的操作。
* 而barrier action又是在其他线程中相应的await()成功返回之后的happen-before操作。
* @since 1.5
* @see CountDownLatch
*
* @author Doug Lea
*/
public class CyclicBarrier {
/**
* 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,
* generation都会改变。有许多generation关联了使用barrier的线程由于不确定的方式,
* 锁可能被分配给等待的线程——但是一次只能激活一个线程(count所应用的线程),其余的要么broken,要么tripped
*/
private static class Generation {
boolean broken = false;
}
....
/**
* Resets the barrier to its initial state. If any parties are
* currently waiting at the barrier, they will return with a
* {@link BrokenBarrierException}. Note that resets <em>after</em>
* a breakage has occurred for other reasons can be complicated to
* carry out; threads need to re-synchronize in some other way,
* and choose one to perform the reset. It may be preferable to
* instead create a new barrier for subsequent use.
* 重置barrier为初始状态,如果任何一方当前处于waiting状态,将返回BrokenBarrierException。
* 请注意,在因其他原因而导致的中断发生后进行复位可能比较复杂;线程需要以其他方式重新同步,
* 并选择一种方式执行重置。当然最好是为后续使用创建一个新的barrier。
*/
public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); // break the current generation
nextGeneration(); // start a new generation
} finally {
lock.unlock();
}
}
....
}
原文:https://www.cnblogs.com/VinnMerlin/p/11706245.html