一、核心代码阅读
await()方法调用的是dowait
/***长循环等待***/private int dowait(boolean timed, long nanos)throws InterruptedException, BrokenBarrierException,TimeoutException {final ReentrantLock lock = this.lock;//获取独占锁lock.lock();try {//将换代信息赋值给变量gfinal Generation g = generation;//如果栅栏损坏,则抛出异常(什么情况会导致栅栏损坏?)if (g.broken)throw new BrokenBarrierException();//如果一个线程的中断标志是True,那么立即损坏栅栏,直接抛出异常if (Thread.interrupted()) {breakBarrier();throw new InterruptedException();}//当有线程调用barrier.await方法时,计数器都减1int index = --count;//最后一个线程调用barrier.await时,计数器减1后变为0if (index == 0) { // trippedboolean ranAction = false;try {//如果创建栅栏时,指定了屏障任务,则最后到达栅栏的线程执行屏障任务final Runnable command = barrierCommand;if (command != null)command.run();ranAction = true;//更新换代处理(先通过Condition唤醒其他线程,然后重置Generation)//最后的线程不需要进入等待状态,会接着执行自己的任务nextGeneration();return 0;} finally {//[异常处理]如果执行屏障任务出错,则忽略异常,并且损坏栅栏if (!ranAction)breakBarrier();}}// loop until tripped, broken, interrupted, or timed outfor (;;) {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();}
二、总结
2.1 try{ block1 }finally { block2 }, 可以看出finally中并没有return语句,也就是说此方法的返回值是block1中的return返回的值。
2.2 为什么此方法需要用ReentrantLock把过程锁住呢?
2.3 for循环是怎么退出的?如果一直循环下去,那么锁是怎么释放掉的?
2.4 await方法逻辑如下,除非发生一下几种情况,否则线程一直处于等待状态。
a 当前线程被其他线程中断。
b 其他的某一个线程中断了处于等待状态的某一线程。
c 最后一个线程到达栅栏。
d 最后一个线程到达栅栏后,执行屏障任务发生异常。
e 超时等待,某一线程等待的时间超过设置时间。
f 某一线程等待barrier超时。
g 栅栏被重置reset。reset方法用户将栅栏重置为初始状态。
三、使用说明
比如说某一团队小组开会,全部成员都到齐后,会议还需要组长到后,才能开始。在组长没有到来之前,小组成员都是相互等待的状态。
