首页 >> 大全

CyclicBarrier源码理解

2023-12-22 大全 21 作者:考证青年

唤醒的两种逻辑:

创建新的一代 时会唤醒所有线程

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

源代码怎么理解__源代码解释

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

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

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

await()方法

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

()

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();}
}

正常唤醒逻辑:()

private void nextGeneration() {// signal completion of last generationtrip.signalAll();count = parties;generation = new Generation();
}

异常唤醒逻辑:()

private void breakBarrier() {//将代中的broken设置为true,表示这一代是被打破了的,再来到这一代的线程,直接抛出异常.generation.broken = true;//重置count为partiescount = parties;//将在trip条件队列内挂起的线程 全部唤醒,唤醒后的线程 会检查当前代 是否是打破的,//如果是打破的话,接下来的逻辑和 开启下一代 唤醒的逻辑不一样.trip.signalAll();
}

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了