一、核心代码阅读

await()方法调用的是dowait

  1. /*
  2. **长循环等待
  3. **
  4. */
  5. private int dowait(boolean timed, long nanos)
  6. throws InterruptedException, BrokenBarrierException,TimeoutException {
  7. final ReentrantLock lock = this.lock;
  8. //获取独占锁
  9. lock.lock();
  10. try {
  11. //将换代信息赋值给变量g
  12. final Generation g = generation;
  13. //如果栅栏损坏,则抛出异常(什么情况会导致栅栏损坏?)
  14. if (g.broken)
  15. throw new BrokenBarrierException();
  16. //如果一个线程的中断标志是True,那么立即损坏栅栏,直接抛出异常
  17. if (Thread.interrupted()) {
  18. breakBarrier();
  19. throw new InterruptedException();
  20. }
  21. //当有线程调用barrier.await方法时,计数器都减1
  22. int index = --count;
  23. //最后一个线程调用barrier.await时,计数器减1后变为0
  24. if (index == 0) { // tripped
  25. boolean ranAction = false;
  26. try {
  27. //如果创建栅栏时,指定了屏障任务,则最后到达栅栏的线程执行屏障任务
  28. final Runnable command = barrierCommand;
  29. if (command != null)
  30. command.run();
  31. ranAction = true;
  32. //更新换代处理(先通过Condition唤醒其他线程,然后重置Generation)
  33. //最后的线程不需要进入等待状态,会接着执行自己的任务
  34. nextGeneration();
  35. return 0;
  36. } finally {
  37. //[异常处理]如果执行屏障任务出错,则忽略异常,并且损坏栅栏
  38. if (!ranAction)
  39. breakBarrier();
  40. }
  41. }
  42. // loop until tripped, broken, interrupted, or timed out
  43. for (;;) {
  44. try {
  45. if (!timed)
  46. trip.await();
  47. else if (nanos > 0L)
  48. nanos = trip.awaitNanos(nanos);
  49. } catch (InterruptedException ie) {
  50. //[异常处理]若其他线程在进行等待或者有时长的等待动作时(不包括最后到达栅栏的线程),发生了中断异常,
  51. //并且栅栏没坏,那么损坏栅栏,抛出中断异常
  52. if (g == generation && ! g.broken) {
  53. breakBarrier();
  54. throw ie;
  55. } else {
  56. // We're about to finish waiting even if we had not
  57. // been interrupted, so this interrupt is deemed to
  58. // "belong" to subsequent execution.
  59. Thread.currentThread().interrupt();
  60. }
  61. }
  62. if (g.broken)
  63. throw new BrokenBarrierException();
  64. //一旦最后一个线程到达栅栏,并且更新换代后,其他的线程返回之前的计数,并且跳出循环
  65. if (g != generation)
  66. return index;
  67. //如果是有时长的等待,并且时间已经到了,那么损坏栅栏,抛出超时异常
  68. if (timed && nanos <= 0L) {
  69. breakBarrier();
  70. throw new TimeoutException();
  71. }
  72. }
  73. } finally {
  74. //释放独占锁
  75. lock.unlock();
  76. }

二、总结

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方法用户将栅栏重置为初始状态。

三、使用说明

比如说某一团队小组开会,全部成员都到齐后,会议还需要组长到后,才能开始。在组长没有到来之前,小组成员都是相互等待的状态。