CyclicBarrier源码分析

CyclicBarrier的结构
public class CyclicBarrier {

/**
 * 存在一个Generation静态内部类
 */ 
private static class Generation {
    boolean broken = false; // 标识CyclicBarrier是否被破坏
}

private final ReentrantLock lock = new ReentrantLock();

private final Condition trip = lock.newCondition(); // 与ReentrantLock绑定的Condition实例

private final int parties; // 用于记录一共有多少个线程需要等待

private final Runnable barrierCommand; // 由最后一个进入await()方法的线程进行调用

private Generation generation = new Generation();

private int count; // 用于记录还需要多少个线程进行等待

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

public CyclicBarrier(int parties) {
    this(parties, null);
}

public int await() throws InterruptedException, BrokenBarrierException {
    try {
        return dowait(false, 0L);
    } catch (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 {
    // ......
}

// 其他省略

}
可以看到CyclicBarrier存在全局的lock、trip、parties、count、barrierCommand以及generation属性,其中parties属性用于记录一共有多少个线程需要等待,而count用于记录还需要多少个线程进行等待。

同时CyclicBarrier中定义了一个Generation静态内部类,该内部类只有一个broken全局属性,用于标识CyclicBarrier是否被破坏,默认为false。

同时CyclicBarrier的构造方法会初始化全局的parties、count以及barrierCommand属性(CyclicBarrier初始化后,count的数量等于parties的数量)

await()方法
由于当创建CyclicBarrier实例之后,线程需要依次调用CyclicBarrier的await()方法让自己进入等待状态,因此从await()方法开始入手。

public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (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));
}
await()方法存在两个重载,区别是一个支持超时,一个不支持超时,最终都会调用dowait()方法(使用timed参数表示是否有超时限制,如果timed参数为true则需要传递具体的超时时间)

dowait()方法
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
// 获取全局的ReentrantLock实例,并进行加锁
final ReentrantLock lock = this.lock;
lock.lock();
try {
// 获取全局的Generation实例,如果Generation中的broken属性为true则表示CyclicBarrier已经被破坏,则直接抛出异常(默认是false)
final Generation g = generation;

    if (g.broken)
        throw new BrokenBarrierException();

    // 如果线程已经被设置了中断标识,则调用breakBarrier()方法,破坏CyclicBarrier
    if (Thread.interrupted()) {
        breakBarrier();
        throw new InterruptedException(); // 抛出异常
    }

    // index属性用于记录还需要多少个线程进行等待
    int index = --count;
    // 如果index等于0,表示当前线程是最后一个进入await()方法的线程,如果barrierCommand不为空,那么执行barrierCommand的run()方法,然后调用nextGeneration()方法,唤醒在指定Condition实例中等待的所有线程,并重置CyclicBarrier,然后线程直接返回,做自己的事情
    if (index == 0) {  // 最后一个线程走这个逻辑
        boolean ranAction = false;
        try {
            final Runnable command = barrierCommand;
            if (command != null)
                command.run();
            ranAction = true;
            nextGeneration();
            return 0;
        } finally {
            // 如果在执行barrierCommand的run()方法时抛出异常,那么ranAction标识为false,那么需要调用breakBarrier()方法,破坏CyclicBarrier
            if (!ranAction)
                breakBarrier();
        }
    }

    // 如果非最后一个线程那么将会往下执行
    
    // 循环
    for (;;) {
        try {
            // 如果没有超时限制,那么直接调用Condition实例的await()方法,让线程在指定的Condition实例中进行等待,并释放掉它拥有的锁
            // 如果有超时限制,那么调用Condition实例的awaitNanos()方法,至多让线程在指定的Condition实例中等待指定的时间,该方法返回线程被唤醒后剩余的毫秒数(超时返回小于等于0),并释放掉它拥有的锁
            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();
            }
        }

        // 当线程被唤醒后将会串行执行以下的逻辑
        
        // 如果发现CyclicBarrier被破坏了,那么就抛出异常
        if (g.broken)
            throw new BrokenBarrierException();

        // 正常情况下,当调用了nextGeneration()方法之后,generation引用就指向一个新的Generation实例,因此g!=generation,那么线程直接返回,做自己的事情
        if (g != generation)
            return index;

        // 如果线程在Condition实例等待的过程中由于达到了超时时间而被唤醒了,那么将会调用breakBarrier()方法,破坏CyclicBarrier
        if (timed && nanos <= 0L) {
            breakBarrier();
            throw new TimeoutException(); // 抛出异常
        }
    }
} finally {
    lock.unlock(); // 解锁
}

}
当线程进入dowait()方法后,需要获取锁,如果当前线程并非最后一个进入await()方法的线程,那么将会在指定的Condition实例中进行等待,然后释放掉它拥有的锁,如果当前线程是最后一个进入await()方法的线程(index==0,表示还需要0个线程进行等待),如果barrierCommand不为空,那么将会执行barrierCommand的run()方法,最后调用nextGeneration()方法。

如果在执行dowait()方法的过程中,线程已经被设置了中断标识,或者最后一个线程在执行barrierCommand的run()方法时抛出异常,或者在指定Condition实例等待的线程由于达到了超时时间而被唤醒,那么都会调用breakBarrier()方法。

nextGeneration()方法
private void nextGeneration() {
// 唤醒在指定Condition实例中等待的所有线程
trip.signalAll();
// 将count的数量设置成parties
count = parties;
// 将generation引用指向一个新的Generation实例
generation = new Generation();
}
nextGeneration()方法用于指向下一个Generation,该方法将会唤醒在指定Condition实例中等待的所有线程,然后将count的数量设置成parties,恢复成CyclicBarrier初始化后的状态,最后将generation引用指向一个新的Generation实例。

breakBarrier()方法
private void breakBarrier() {
// 将Generation实例的broken属性设置为true,表示CyclicBarrier已经被破坏
generation.broken = true;
// 将count的数量设置回parties
count = parties;
// 唤醒在指定Condition实例中等待的所有线程
trip.signalAll();
}
breakBarrier()方法用于破坏CyclicBarrier,将Generation实例的broken属性设置为true,表示CyclicBarrier已经被破坏,然后将count的数量设置成parties,最后唤醒在指定Condition实例中等待的所有线程。

reset()方法
public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); // 感觉是多余的
nextGeneration(); // 指向下一个Generation
} finally {
lock.unlock();
}
}
亚马逊测评 www.yisuping.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值