CyclicBarrier

CyclicBarrier 是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)
之后同时释放执行。CyclicBarrier 可以重置同步器的状态(循环使用栅栏),而 CountDownLatch 则不能。
CyclicBarrier 能指定一个 barrierCommand 在栅栏释放后执行归并。

创建实例

    /**
* 栅栏的分代,循环递增
*/
private static class Generation {
Generation() {}
// 此带的栅栏是否已经被破坏
boolean broken;
} /** 保护进入屏障的锁 */
private final ReentrantLock lock = new ReentrantLock();
/** 屏障释放条件 */
private final Condition trip = lock.newCondition();
/** 参与者数目 */
private final int parties;
/** 屏障释放后执行的任务 */
private final Runnable barrierCommand;
/** 当前的代 */
private Generation generation = new Generation(); /**
* 待进入屏障的线程数
*/
private int count; /**
* 创建具有 parties 个参与者,无后置任务的屏障
*/
public CyclicBarrier(int parties) {
this(parties, null);
} /**
* 创建具有 parties 个参与者,后置任务为 barrierAction 的屏障
*/
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) {
throw new IllegalArgumentException();
}
this.parties = parties;
count = parties;
barrierCommand = barrierAction;
}

同步阻塞

    /**
* 1)尝试阻塞等待所有的参与者都到达屏障,如果当前线程是最后一个参与者,则唤醒所有其他阻塞的参与者线程
* 2)当前线程被中断
* 3)任何一个参与者线程被中断
* 4)任何一个参与者线程超时
* 5)屏障的 reset 方法被调用
*/
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (final TimeoutException toe) {
throw new Error(toe); // cannot happen
}
} public int await(long timeout, TimeUnit unit)
throws InterruptedException,
BrokenBarrierException,
TimeoutException {
return dowait(true, unit.toNanos(timeout));
} private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
// 读取锁
final ReentrantLock lock = this.lock;
// 锁定
lock.lock();
try {
// 读取当前代
final Generation g = generation; // 如果屏障已经破裂
if (g.broken) {
throw new BrokenBarrierException();
} // 当前线程被其他线程中断
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
} // 剩余参与者数
final int index = --count;
// 如果当前线程是最后一个参与者
if (index == 0) { // tripped
boolean ranAction = false;
try {
// 如果后置任务不为 null,则运行它
final Runnable command = barrierCommand;
if (command != null) {
command.run();
}
ranAction = true;
// 递增分代
nextGeneration();
return 0;
} finally {
// 任务运行时出现异常,也要打破屏障
if (!ranAction) {
breakBarrier();
}
}
} // loop until tripped, broken, interrupted, or timed out
for (;;) {
try {
// 1)如果不是超时模式,则一直阻塞
if (!timed) {
trip.await();
// 2)超时阻塞
} else if (nanos > 0L) {
nanos = trip.awaitNanos(nanos);
}
// 如果线程被中断
} catch (final 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;
} // 当前线程等待超时
if (timed && nanos <= 0L) {
// 打破屏障
breakBarrier();
throw new TimeoutException();
}
}
} finally {
// 释放锁
lock.unlock();
}
}

CyclicBarrier 源码分析的更多相关文章

  1. Java - "JUC" CyclicBarrier源码分析

    Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例 CyclicBarrier简介 CyclicBarrier是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 ...

  2. 并发工具CyclicBarrier源码分析及应用

      本文首发于微信公众号[猿灯塔],转载引用请说明出处 今天呢!灯塔君跟大家讲: 并发工具CyclicBarrier源码分析及应用 一.CyclicBarrier简介 1.简介 CyclicBarri ...

  3. 并发编程之 CyclicBarrier 源码分析

    前言 在之前的介绍 CountDownLatch 的文章中,CountDown 可以实现多个线程协调,在所有指定线程完成后,主线程才执行任务. 但是,CountDownLatch 有个缺陷,这点 JD ...

  4. concurrent(六)同步辅助器CyclicBarrier & 源码分析

    参考文档:Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例:https://www.cnblogs.com/skywang12345/p/3533995.html简介Cy ...

  5. Java并发编程笔记之CyclicBarrier源码分析

    JUC 中 回环屏障 CyclicBarrier 的使用与分析,它也可以实现像 CountDownLatch 一样让一组线程全部到达一个状态后再全部同时执行,但是 CyclicBarrier 可以被复 ...

  6. CyclicBarrier源码分析

    CyclicBarrier是通过ReentrantLock(独占锁)和Condition来实现的.下面,我们分析CyclicBarrier中3个核心函数: 构造函数, await()作出分析. 1. ...

  7. 多线程高并发编程(5) -- CountDownLatch、CyclicBarrier源码分析

    一.CountDownLatch 1.概念 public CountDownLatch(int count) {//初始化 if (count < 0) throw new IllegalArg ...

  8. Java并发系列[8]----CyclicBarrier源码分析

    现实生活中我们经常会遇到这样的情景,在进行某个活动前需要等待人全部都齐了才开始.例如吃饭时要等全家人都上座了才动筷子,旅游时要等全部人都到齐了才出发,比赛时要等运动员都上场后才开始.在JUC包中为我们 ...

  9. 【JUC】JDK1.8源码分析之CyclicBarrier(四)

    一.前言 有了前面分析的基础,现在,接着分析CyclicBarrier源码,CyclicBarrier类在进行多线程编程时使用很多,比如,你希望创建一组任务,它们并行执行工作,然后在进行下一个步骤之前 ...

随机推荐

  1. application详解

    Application对象是HttpApplicationState类的一个实例,Application状态是整个应用程序全局的.本文主要详细介绍Application对象的用法. 一.全局应用程序类 ...

  2. 【nginx】上传文件error报413 Request Entity Too Large

    nginx配置增大上传文件限制 如果访问地址是通过nginx转发配置的 server{ ... ... client_max_body_size 50M; ... ... } ingress配置增大上 ...

  3. oracle数据库中的游标

    oracle中的游标,游标的概念与作用,游标的分类,游标的使用. 一,游标的概念与作用 摘自百度百科:游标(Cursor)是处理数据的一种方法,为了查看或者处理结果集中的数据,游标提供了在结果集中一次 ...

  4. [七月挑选]写个定时任务,从github下载代码到阿里ECS服务器上

    title: 写个定时任务,从github下载代码到阿里ECS服务器上 根据前几篇博客中能自己创建一个博客,并在github.io上访问到自己的博客,但是如果自己有服务器,那怎么能定时获取github ...

  5. 基于Kintex Ultrasacle的万兆网络光纤 PCIe加速卡416 光纤PCIe卡

    基于Kintex Ultrasacle的万兆网络光纤 PCIe加速卡 一.产品概述 本卡为企业级别板卡,可用于数据中心,安全领域数据采集处理.标准PCI Express全高板,适用于普通服务器.工作站 ...

  6. Python自动化学习--异常提示

    举例:打开一个不存在的文件时: >>open("abc.txt","r")会提示错误 Traceback (most recent call las ...

  7. 【原】cmdline传递参数 uboot-->kernel-->fs

    在uboot中设置bootargs环境变量,在kernel启动后cat /proc/cmdline可以看到bootargs的值. U-boot的环境变量值得注意的有两个: bootcmd 和boota ...

  8. mock.js模拟ajax数据请求

    在我们开发过程中存在着前端页面ui完成了,但是没有接口进行联调数据的情况,现在介绍一下用mock.js来完成数据的请求.这样在后期我们的后台接口完成后只需要更改请求的接口名字即可!前提是你的模拟字段名 ...

  9. Flask实现分页功能

    可以参考: https://blog.csdn.net/weixin_36380516/article/details/80295101 也可以参考我的代码: https://github.com/z ...

  10. CF261E Maxim and Calculator (质数,完全背包)

    CF261E Maxim and Calculator 题目大意: 有两个初始参数 $ a=1 $ , $ b=0 $ ,你可以对它们进行两个操作: $ b~+=1 $ 或 $ a~\times =b ...