JUC锁框架源码阅读-CyclicBarrier
说明
使用方式可以参考:https://www.cnblogs.com/LQBlog/p/8983019.html
初始化
main
public static void main(String[] args) throws InterruptedException, BrokenBarrierException { /** * <1>初始化 * 第一个参数栅栏数量 * 第二个参数 最终执行任务 */ CyclicBarrier cyclicBarrier=new CyclicBarrier(3, new Runnable() { @Override public void run() { System.out.println("最终执行任务"); } }); cyclicBarrier.await(); }
1.设置栅栏数量 底层是依赖ReentrantLock和 Condition
2.每次await 先试用RenentrantLock加锁。然后栅栏-1 保证原子性和使用Condition
3.如果栅栏-完之后大于1 则调用Condition await 放入AQS wait队列 同时释放锁
4.如果栅栏-完之后==0 如果有最终任务则调用最终任务 然后调用Condition的SingleAll()将所有wait队列加入到CLH队列
5.CLH队列依次获取锁,然后到finally 释放锁
<2>初始化
public CyclicBarrier(int parties, Runnable barrierAction) { if (parties <= 0) throw new IllegalArgumentException(); //中间变量 用于重置时使用 this.parties = parties;
//设置栅栏数量 this.count = parties; //最终执行任务 this.barrierCommand = barrierAction; }
开启栅栏await
public static void main(String[] args) throws InterruptedException, BrokenBarrierException { /** * 初始化 * 第一个参数栅栏数量 * 第二个参数 最终执行任务 */ CyclicBarrier cyclicBarrier=new CyclicBarrier(3, new Runnable() { @Override public void run() { System.out.println("最终执行任务"); } }); //<1> cyclicBarrier.await(); }
<1>await
public int await() throws InterruptedException, BrokenBarrierException { try { //<2>默认不超时 return dowait(false, 0L); } catch (TimeoutException toe) { throw new Error(toe); // cannot happen } }
<2>dowait
private int dowait(boolean timed, long nanos) throws InterruptedException, BrokenBarrierException, TimeoutException { //内部使用的是RenntranLock实现 final ReentrantLock lock = this.lock; //加锁 lock.lock(); try { //内部类 只存储了bool broken=false 表示已经中断 final CyclicBarrier.Generation g = generation; //判断是否中断 if (g.broken) throw new BrokenBarrierException(); //判断是否线程中断 if (Thread.interrupted()) {
//<3>记录异常 重置栅栏 并唤醒所有等待线程 breakBarrier(); throw new InterruptedException(); } //栅栏-1 int index = --count; //如果栅栏=0则触发最终任务调用 if (index == 0) { // tripped boolean ranAction = false; try { //调用最终任务 final Runnable command = barrierCommand; if (command != null) command.run(); ranAction = true; //<4>唤醒所有等待线程 并重置栅栏 nextGeneration(); return 0; } finally { //表示出现了异常 栅栏终止 if (!ranAction) //<3>出现异常 breakBarrier(); } } // 针对有超时时间的栅栏 for (;;) { try { //没有超时时间等待 直接调用condition等待 if (!timed) trip.await(); 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(); if (g != generation) return index; //设置了等待时间 但是等待时间小于0 报错 if (timed && nanos <= 0L) { breakBarrier(); throw new TimeoutException(); } } } finally { //释放锁 lock.unlock(); } }
<3>breakBarrier
private void breakBarrier() { //设置表示 已经中断 generation.broken = true; //通过中间变量重置 count = parties; //唤醒所有等待线程 trip.signalAll(); }
<4>nextGeneration
private void nextGeneration() { //唤醒所有等待线程 trip.signalAll(); //重置栅栏 count = parties; //重置异常记录 generation = new CyclicBarrier.Generation(); }