CyclicBarrier解读
来源:互联网 发布:nginx 隐藏源ip 编辑:程序博客网 时间:2024/06/05 23:02
CyclicBarrier能实现与CountDownLatch相同的功能,但是两者的实现上是不一样的,而且CountDownLatch每次使用完再继续使用就会有问题,而CyclicBarrier不一样,可以一直使用,下面我们来分析一下CyclicBarrier的代码。
CyclicBarrier的代码中并没有定义自己的同步器类,他是基于ReentrantLock和Condition来实现的 /** The lock for guarding barrier entry */
private final ReentrantLock lock = new ReentrantLock();
/** Condition to wait on until tripped */
private final Condition trip = lock.newCondition();
我们这样子创建CyclicBarrier 对象,
private final static CyclicBarrier CYCLIC_BARRIER = new CyclicBarrier( 3);当然也可以传入一个实现Runnable接口的对象,每次任务完成时都显示调用这个Runnable任务。CYCLIC_BARRIER 最终调用的构造方法如下:
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
我们传入的数量3被赋值给了CyclicBarrier中的parties和count 属性,两个属性的定义如下:
private final int parties;
private int count;
注意parties属性是final的,一旦初始化完成就不允许再更改了。
接下来我们看看CYCLIC_BARRIER.await();的实现,最终调用的是CyclicBarrier中的dowait()方法
/**
* Main barrier code, covering the various policies.
*/
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) { // tripped
boolean ranAction = false;
try {
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 {
if (!timed)
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();
}
}
if (g.broken)
throw new BrokenBarrierException();
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
代码主要的逻辑就是先赋值
int index = --count;count中存放的就是我们传入的参数3,前两次--count赋值给index后肯定是大于0的,往下走就会进入一个自旋的方法,最后调用到Condition对象的await()方法。
在这里我们要先来看看这个ReentrantLock中的这个Condition是个什么东东。
public Condition newCondition() {
return sync.newCondition();
}
翻开源码看到这个newCondition方法是调用同步器的newCondition方法创建的,同步器中的newCondition代码如下:
final ConditionObject newCondition() {
return new ConditionObject();
}
这个ConditionObject对象实际上是在AQS中定义的一个内部类。ConditionObject对象的await方法如下所示:
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
阅读代码会发现ConditionObject对象的中也维护了一个队列,调用CYCLIC_BARRIER.await();方法的线程会阻塞在await这个方法之中,阻塞之前调用 fullyRelease(node);方法释放了ReentrantLock的锁。
当最后一个线程最后一个--count赋值index为0(int index = --count;)的时候,会走dowait方法的一下这块逻辑
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
nextGeneration()方法的代码如下:
private void nextGeneration() {
// signal completion of last generation
trip.signalAll();
// set up next generation
count = parties;
generation = new Generation();
}
调用Condition对象trip的signalAll();方法唤醒阻塞在ConditionObject对象中的线程中,大家就都会执行过,
然后将count用final的parties变量重新赋值,这样count 就恢复了,从而这个CyclicBarrier对象以后还是可以继续使用。
- CyclicBarrier解读
- cyclicBarrier
- CyclicBarrier
- CyclicBarrier
- CyclicBarrier
- CyclicBarrier
- CyclicBarrier
- CyclicBarrier
- CyclicBarrier
- CyclicBarrier
- CyclicBarrier
- cyclicBarrier
- CyclicBarrier
- CyclicBarrier
- CyclicBarrier
- CyclicBarrier
- CyclicBarrier
- CyclicBarrier
- 【LeetCode从零单排】No15 3Sum
- 行为型模式-策略
- ThreadPoolExecutor解读
- 浅析同义词--Synonym
- MarkDown编辑器
- CyclicBarrier解读
- MVC入门教程八[MvcPager分页控件的使用]
- CountDownLatch解读
- Android 随机数的生成
- 简单模拟对大数据进行排序的整个过程
- Linux下用Xdebug调试php
- ThreadLocal解读
- Apache http server linux centos 安装
- Java使用dom读取xml文件