博客
关于我
CyclicBarrier源码探究 (JDK 1.8)
阅读量:408 次
发布时间:2019-03-06

本文共 2967 字,大约阅读时间需要 9 分钟。

CyclicBarrier详解:从实现到使用技巧

1. 相关字段

CyclicBarrier(回环栅栏)通过以下字段实现线程安全:

  • ReentrantLock lock:用于保证线程安全,实现了独占锁机制。
  • Condition trip:线程阻塞时的等待条件。
  • int parties:需要等待的线程数。
  • Runnable barrierCommand:栅栏打开时首先执行的任务。
  • Generation generation:记录当前栅栏所处的代号。
  • int count:当前还需要等待的线程数。

2. 构造函数

CyclicBarrier 提供两个重载构造函数:

public CyclicBarrier(int parties) {    this(parties, null);}public CyclicBarrier(int parties, Runnable barrierAction) {    if (parties <= 0)        throw new IllegalArgumentException();    this.parties = parties;    this.count = parties;    this.barrierCommand = barrierAction;}

3. 核心方法

3.1 await方法

  • await():无参数版本,调用dowait(false, 0L)
  • await(long timeout, TimeUnit unit):带有超时参数,调用dowait(true, unit.toNanos(timeout))

3.2 dowait方法

dowait 是核心逻辑,实现了栅栏的等待与唤醒机制:

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();        }        int index = --count;        if (index == 0) {            boolean ranAction = false;            try {                final Runnable command = barrierCommand;                if (command != null)                    command.run();                ranAction = true;                nextGeneration();                return 0;            } finally {                if (!ranAction)                    breakBarrier();            }        }        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();    }}

3.2.1 breakBarrier方法

private void breakBarrier() {    generation.broken = true;    count = parties;    trip.signalAll();}

3.2.2 nextGeneration方法

private void nextGeneration() {    trip.signalAll();    count = parties;    generation = new Generation();}

3.2.3 reset方法

public void reset() {    final ReentrantLock lock = this.lock;    lock.lock();    try {        breakBarrier();        nextGeneration();    } finally {        lock.unlock();    }}

4. 问题解析

4.1 dowait中的锁释放问题

dowait方法中,锁是在finally块中释放的。第一个线程获取锁后进入等待状态,其他线程如何获取锁?答案在于Conditionawait方法内部,通过unparkSuccessor唤醒后继线程,允许它们获取锁继续执行。

5. 更新日志

  • 3.19日更新了问题解析的问题1。

转载地址:http://slkkz.baihongyu.com/

你可能感兴趣的文章
Objective-C实现批量修改文件类型算法(附完整源码)
查看>>
Objective-C实现找出一个数的质因数primeFactors算法(附完整源码)
查看>>
Objective-C实现找出买卖股票的最大利润算法(附完整源码)
查看>>
Objective-C实现找出二维数组中的鞍点(附完整源码)
查看>>
Objective-C实现找出由两个 3 位数字的乘积构成的最大回文数的算法 (附完整源码)
查看>>
Objective-C实现找到具有 500 个除数的第一个三角形数算法(附完整源码)
查看>>
Objective-C实现抓包实例(附完整源码)
查看>>
Objective-C实现抽签抓阄(附完整源码)
查看>>
Objective-C实现抽象工厂模式(附完整源码)
查看>>
Objective-C实现拉格朗日插值法(附完整源码)
查看>>
Objective-C实现指定内存空间获取时间的函数(附完整源码)
查看>>
Objective-C实现按位倒序(附完整源码)
查看>>
Objective-C实现按位运算符乘以无符号数multiplyUnsigned算法(附完整源码)
查看>>
Objective-C实现排队叫号系统(附完整源码)
查看>>
Objective-C实现控制NRP8S功率计读取功率 (附完整源码)
查看>>
Objective-C实现控制程控电源2306读取电流 (附完整源码)
查看>>
Objective-C实现摄氏温度和华氏温度互转(附完整源码)
查看>>
Objective-C实现播放器(附完整源码)
查看>>
Objective-C实现操作MySQL(附完整源码)
查看>>
Objective-C实现操作注册表 (附完整源码)
查看>>