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方法的执行流程如下:
欢迎留言补充,共同交流。个人微信公众号求关注: