CyclicBarrier源码理解

阅读: 评论:0

CyclicBarrier源码理解

CyclicBarrier源码理解

CyclicBarrier

唤醒的两种逻辑:

  1. 创建新的一代 newGeneration 时会唤醒所有线程 signalAll

  2. 打破当前代 将broken修改为true时 会唤醒所有线程 signalAll 但是这种会抛出Broken异常

    tips: 怎么才会打破当前代?就是当前线程给中断抛出异常时,就会去调用brokenBarrier方法打破当前代

CyclicBarrier里面有个变量broken,当broken为true时,表示当前‘代’被打破,来到这个代的线程会抛出BrokenException异常,

而在这个代被挂起的线程,都会被唤醒并且抛出BrokenException异常

await()方法

public int await() throws InterruptedException, BrokenBarrierException {try {return dowait(false, 0L);//false表示不支持超时机制} catch (TimeoutException toe) {throw new Error(toe); // cannot happen}
}

dowait()

private int dowait(boolean timed, long nanos)throws InterruptedException, BrokenBarrierException,TimeoutException {final ReentrantLock lock = this.lock;//加锁的原因:下面需要用到conditionlock.lock();try {final Generation g = generation;/**/异常逻辑if (g.broken)throw new BrokenBarrierException();if (Thread.interrupted()) {breakBarrier();throw new InterruptedException();}**///调用一次await方法就会减一次count,直到最后一个线程‘上车’就发车int index = --count;//说明人到齐了,准备发车if (index == 0) {  // trippedboolean ranAction = false;try {//这个是表示最后一个线程到达需要完成的动作final Runnable command = barrierCommand;if (command != null)command.run();ranAction = true;//开启新的一代,唤醒所有给挂起的线程/**{1.唤醒所有线程2.重置count3.开启新的一代}**/nextGeneration();return 0;} finally {if (!ranAction)breakBarrier();}}//如果当前线程不是最后一个线程的话,就走下面自旋的逻辑for (;;) {try {if (!timed)//如果不是支持超时等待的话,就走condition的await()逻辑,会释放锁,加入条件队列尾部,挂起自己等待被唤醒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();}}//执行到这里,1.最后一个线程开启了新的一代,唤醒了所有线程//2.gengration被打破,异常唤醒//3.当前线程支持超时机制,并且超时了,被加入阻塞队列,然后拿到锁了给唤醒了//这个是 2 那种情况if (g.broken)throw new BrokenBarrierException();//这里是 1 那种情况if (g != generation)return index;//这里是 3 那种情况if (timed && nanos <= 0L) {breakBarrier();throw new TimeoutException();}}} finally {lock.unlock();}
}
正常唤醒逻辑:nextGeneration()
private void nextGeneration() {// signal completion of last generationtrip.signalAll();count = parties;generation = new Generation();
}
异常唤醒逻辑:breakGeneration()
private void breakBarrier() {//将代中的broken设置为true,表示这一代是被打破了的,再来到这一代的线程,直接抛出异常.generation.broken = true;//重置count为partiescount = parties;//将在trip条件队列内挂起的线程 全部唤醒,唤醒后的线程 会检查当前代 是否是打破的,//如果是打破的话,接下来的逻辑和 开启下一代 唤醒的逻辑不一样.trip.signalAll();
}

本文发布于:2024-02-01 23:47:15,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170680741639953.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:源码   CyclicBarrier
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23