zoukankan      html  css  js  c++  java
  • 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();
        }
  • 相关阅读:
    senlin __init__() got an unexpected keyword argument 'additional_headers'
    Delphi 全局画点TCanvas.Pixels[X,Y]
    sql server 列修改null 变成not null
    Delphi记录record中的变体
    delphi无边框可拖动窗体
    bootstrap相关资料
    重装windows导致grub损坏
    RabbitMQ的安装(Docker安装)
    RabbitMQ的安装以及使用(Windows环境)
    如果安装rabittmq后,输入http://localhost:15672不出页面的
  • 原文地址:https://www.cnblogs.com/LQBlog/p/15224219.html
Copyright © 2011-2022 走看看