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();
    }

 

posted @ 2021-09-03 17:56  意犹未尽  阅读(32)  评论(0编辑  收藏  举报