CyclicBarrier的字面意思是循环屏障。允许一组线程达到一个屏障(或者同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被拦截的线程才会继续运行。
使用实例
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
new Thread(new Action(cyclicBarrier)).start();
new Thread(new Action(cyclicBarrier)).start();
}
static class Action implements Runnable{
private CyclicBarrier cyclicBarrier;
public Action(CyclicBarrier cyclicBarrier){
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
System.out.println(Thread.currentThread()+" get ready");
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+" work done");
}
}
}
复制代码
实现原理
通过查看源码可知await()方法由dowait()方法完成的,源码如下:
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
// 1、获取锁并加锁
final ReentrantLock lock = this.lock;
lock.lock();
try {
// 2、获取代表屏障使用的generation实例
final Generation g = generation;
if (g.broken)
throw new BrokenBarrierException();
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
// 3、被拦截的线程数的副本值 - 1
int index = --count;
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
// 5、唤醒被拦截的线程和初始化下一次屏障使用
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
// loop until tripped, broken, interrupted, or timed out
// 4、当前线程进入自旋过程,释放锁等待被唤醒
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();
}
}
复制代码
dowait方法的执行流程如下:
欢迎留言补充,共同交流。个人微信公众号求关注: