1. private int dowait(boolean timed, long nanos)
  2. throws InterruptedException, BrokenBarrierException,
  3. TimeoutException {
  4. final ReentrantLock lock = this.lock;
  5. lock.lock();
  6. try {
  7. final Generation g = generation;
  8. if (g.broken)
  9. throw new BrokenBarrierException();
  10. if (Thread.interrupted()) {
  11. breakBarrier();
  12. throw new InterruptedException();
  13. }
  14. int index = --count;
  15. if (index == 0) { // tripped
  16. boolean ranAction = false;
  17. try {
  18. final Runnable command = barrierCommand;
  19. if (command != null)
  20. command.run();
  21. ranAction = true;
  22. nextGeneration();
  23. return 0;
  24. } finally {
  25. if (!ranAction)
  26. breakBarrier();
  27. }
  28. }
  29. // loop until tripped, broken, interrupted, or timed out
  30. for (;;) {
  31. try {
  32. if (!timed)
  33. trip.await();
  34. else if (nanos > 0L)
  35. nanos = trip.awaitNanos(nanos);
  36. } catch (InterruptedException ie) {
  37. if (g == generation && ! g.broken) {
  38. breakBarrier();
  39. throw ie;
  40. } else {
  41. // We're about to finish waiting even if we had not
  42. // been interrupted, so this interrupt is deemed to
  43. // "belong" to subsequent execution.
  44. Thread.currentThread().interrupt();
  45. }
  46. }
  47. if (g.broken)
  48. throw new BrokenBarrierException();
  49. if (g != generation)
  50. return index;
  51. if (timed && nanos <= 0L) {
  52. breakBarrier();
  53. throw new TimeoutException();
  54. }
  55. }
  56. } finally {
  57. lock.unlock();
  58. }
  59. }
  60. private void doSignalAll(Node first) {
  61. lastWaiter = firstWaiter = null;
  62. do {
  63. Node next = first.nextWaiter;
  64. first.nextWaiter = null;
  65. transferForSignal(first);
  66. first = next;
  67. } while (first != null);
  68. }
  69. final boolean transferForSignal(Node node) {
  70. /*
  71. * If cannot change waitStatus, the node has been cancelled.
  72. */
  73. if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
  74. return false;
  75. /*
  76. * Splice onto queue and try to set waitStatus of predecessor to
  77. * indicate that thread is (probably) waiting. If cancelled or
  78. * attempt to set waitStatus fails, wake up to resync (in which
  79. * case the waitStatus can be transiently and harmlessly wrong).
  80. */
  81. Node p = enq(node);
  82. int ws = p.waitStatus;
  83. if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
  84. LockSupport.unpark(node.thread);
  85. return true;
  86. }

流程

03-26 CyclicBarrier执行流程 - 图1