AQS
用于快速实现同步器的抽象父类,这里面定义了基本的一些实现
// 需要重点关注的属性
// 同步器状态
private volatile int state;
// 等待队列的头节点 lazily initialized
private transient volatile Node head;
// 等待队列的尾节点 lazily initialized
private transient volatile Node tail;
独占锁的抽象逻辑结构
AQS 中独占锁的获取锁的抽象逻辑结构: acquire 和 release 方法的具体实现即可:
// acquire方法的具体实现过程(独占模式获取锁,不响应中断)
public final void acquire(int arg) {
// 直接尝试获取锁资源,未成功尝试加入等待队列
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
// 加入等待队列就是懒惰创建对应的等待节点
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
// 尾节点为空代表等待队列为空,需要插入一个dummy哨兵节点,直接进入enq
if (pred != null) {
node.prev = pred;
// 尝试设置该节点为最后一个节点
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
// 返回该节点
return node;
}
private Node enq(final Node node) {
// 不断自旋
for (;;) {
Node t = tail;
// 尝试初始化头节点
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
// 加到尾部去
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
// 尝试进行排队
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
// 不断自旋
for (;;) {
// 获取尾节点的前驱节点
final Node p = node.predecessor();
// 如果前驱节点是哨兵节点,尝试获取独占锁,
if (p == head && tryAcquire(arg)) {
// 成功之后将该节点作为头节点,原有的哨兵头节点的依赖解除,快速实现GC
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// 判断是否应该阻塞,若应该就尝试阻塞
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
// 根据前驱节点的状态判断是否应该阻塞该节点
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
// 前驱节点的状态为-1:SIGNAL 尝试唤醒后继节点则需要阻塞,返回true
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
return true;
// 前驱节点状态为正数,表示被取消,需要跳过前驱节点找到更前面状态 <= 0的节点
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
// 更改该节点的前驱节点,并返回不阻塞,尝试重试
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
// 前驱节点为0,需要改为-1,并在接下来的情况重试
// 前驱节点为-3,涉及到共享锁
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
public final boolean release(int arg) {
// 释放逻辑具体实现
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
// 尝试唤醒阻塞队列的第一个节点
unparkSuccessor(h);
return true;
}
return false;
}
// 独占模式,但是响应中断:
public final void acquireInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
}
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
// 直接向上抛出异常,响应中断
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
共享锁的抽象逻辑结构
共享模式下的获取锁的抽象逻辑结构:acquireShared 和 releaseShared(同样需要区分是否响应中断)
public final void acquireShared(int arg) {
// 尝试获取共享锁,这里不再只有成功或者失败,而是根据存在的值来判断成功与否
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
// 尝试加入等待队列
private void doAcquireShared(int arg) {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
// 是头节点
if (p == head) {
// 获取共享资源
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
if (interrupted)
selfInterrupt();
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
private void setHeadAndPropagate(Node node, int propagate) {
Node h = head; // Record old head for check below
setHead(node);
/*
* Try to signal next queued node if:
* Propagation was indicated by caller,
* or was recorded (as h.waitStatus either before
* or after setHead) by a previous operation
* (note: this uses sign-check of waitStatus because
* PROPAGATE status may transition to SIGNAL.)
* and
* The next node is waiting in shared mode,
* or we don't know, because it appears null
*
* The conservatism in both of these checks may cause
* unnecessary wake-ups, but only when there are multiple
* racing acquires/releases, so most need signals now or soon
* anyway.
*/
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
Node s = node.next;
if (s == null || s.isShared())
doReleaseShared();
}
}
内部类 ConditionObject 和 Node 的解析
Node类解析
Node 类是 AQS 中等待的队列的一个单元,也是一个节点,每个线程都是以 Node 的形式存在的。主要属性如下:
// 等待状态:
// CANCELLED = 1; 表示被取消
// SIGNAL = -1; 有责任唤醒后继节点
// CONDITION = -2; 存在于等待队列中
// PROPAGATE = -3; 用于共享锁
// 默认为0 ; 表示未设置状态
volatile int waitStatus;
// 前指针
volatile Node prev;
// 后指针
volatile Node next;
// 当前节点对应的线程
volatile Thread thread;
ConditionObject 类解析
用于条件变量的类对象,实现按条件唤醒对应的线程。
// 关键代码解析
// 第一个等待对象head
private transient Node firstWaiter;
// 最后一个等待对象tail
private transient Node lastWaiter;
// 所有条件变量等待的入口函数
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
// 创建一个对应的等待队列节点
Node node = addConditionWaiter();
// 释放掉该线程的所持有的锁资源,
int savedState = fullyRelease(node);
int interruptMode = 0;
// 判断是否存在于同步队列中(因为后续的signal会将条件节点放到同步队列中)
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
// 清除条件队列,删除不是Condition的节点
unlinkCancelledWaiters();
if (interruptMode != 0)
// interrupt处理或者throw InterruptedException
reportInterruptAfterWait(interruptMode);
}
// 唤醒函数
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
// 具体的唤醒逻辑
doSignal(first);
}
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
// 将该条件队列的第一个节点转移到同步队列中,不成功就继续找后续节点
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
final boolean transferForSignal(Node node) {
// 将节点状态改为0,准备放入同步队列
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
// 放入同步队列,返回其前驱节点
Node p = enq(node);
int ws = p.waitStatus;
// 修改前驱节点为 -1 用于唤醒该节点
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
ReentrantLock
一款常用的互斥锁,可以实现公平锁和非公平锁,基于 AQS 进行的实现。都可以实现可重入,体现于 state 的值并非单一的 0 或 1,而是 正数 和 0,正数表示线程的加锁次数,体现可重入。
非公平锁的同步器实现:
// 1. 重写对应的tryAcquire方法,这里存在于ReentrantLock的Sync内部类
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 这里是不同之处。非公平锁,只要发现未加锁就会去尝试获取锁
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
// 2. Lock接口的lock方法:
final void lock() {
// 直接尝试获取锁
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
// 这里内部会去直接调用nonfairTryAcquire
acquire(1);
}
// 3. 释放锁:非公平锁和公平锁同理,两者只在争抢锁存在差别
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
// 判断释放锁的线程
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 判断可重入次数是否释放完
if (c == 0) {
free = true;
// 注意这里先设置 owner 为null,因为后面的 state 是 volatile 修饰的,可以保证该变量可见于所有线程,并且保证 state 被改后共享资源线程安全
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
公平锁的同步器实现:
// 1. 直接尝试获取锁,走下面的具体逻辑,没有了直接的
final void lock() {
acquire(1);
}
/**
* Fair version of tryAcquire. Don't grant access unless * recursive call or no waiters or is first. */protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 没线程拥有锁,需要先判断是否存在有线程等待,有等待的先让等待的获取锁(体现了公平性)
if (!hasQueuedPredecessors() &&
// 只有没有线程等待,并且自己获取到了锁,才会设置 owner
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
} // 可重入的实现
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
LongAdder
原子累加器的实现:通过为不同线程分配不同的槽位,实现多个线程无干扰的并发累加,最终求和,降低 CAS 的冲突,从而提高效率
// LongAdder的累加一定始于add方法
public void add(long x) {
Cell[] as; long b, v; int m; Cell a;
// cells是累加槽位,
if ((as = cells) != null || !casBase(b = base, b + x)) {
boolean uncontended = true;
// 没有初始化cells,长度小于1,对应的槽位未初始化,槽位存在竞争,CAS对应累加槽位失败
// 上述情况都会进入longAccumulate
if (as == null || (m = as.length - 1) < 0 ||
(a = as[getProbe() & m]) == null ||
!(uncontended = a.cas(v = a.value, v + x)))
longAccumulate(x, null, uncontended);
}}
final void longAccumulate(long x, LongBinaryOperator fn,
boolean wasUncontended) {
int h;
// 判断对应线程是否分配一个槽位
if ((h = getProbe()) == 0) {
// 未分配,需要分配一个槽位
ThreadLocalRandom.current(); // force initialization
h = getProbe();
// wasUncontended标识槽位的竞争,这里true标识没有竞争
wasUncontended = true;
}
boolean collide = false; // True if last slot nonempty
for (;;) {
Cell[] as; Cell a; int n; long v;
// 1. cells已经被初始化了
if ((as = cells) != null && (n = as.length) > 0) {
// 槽位未被初始化,懒惰创建
if ((a = as[(n - 1) & h]) == null) {
if (cellsBusy == 0) { // Try to attach new Cell
// 加锁创建对应的cell,乐观创建,先创建再使用
Cell r = new Cell(x); // Optimistically create
if (cellsBusy == 0 && casCellsBusy()) {
boolean created = false;
try { // Recheck under lock
Cell[] rs; int m, j;
if ((rs = cells) != null &&
(m = rs.length) > 0 &&
rs[j = (m - 1) & h] == null) {
rs[j] = r;
created = true;
}
} finally {
cellsBusy = 0;
}
if (created)
break;
// 防止槽位被其他线程竞争创建
continue; // Slot is now non-empty
}
}
// 存在扩容,防止争抢扩容,直接进入下一次尝试
collide = false;
}
// 存在竞争,直接尝试下一次,快速失败,不去进行CAS操作
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash
// CAS尝试累加
else if (a.cas(v = a.value, ((fn == null) ? v + x :
fn.applyAsLong(v, x))))
break;
// cell大小超过CPU核数,或者已经被扩容,直接快速失败,进入下面的逻辑
else if (n >= NCPU || cells != as)
collide = false; // At max size or stale
// 快速失败,直接进入下一轮自旋,防止再扩容争抢资源,若是因为核数过大可以一直防止扩容
else if (!collide)
collide = true;
// 扩容逻辑,争抢对应的cellsBusy锁
else if (cellsBusy == 0 && casCellsBusy()) {
try {
if (cells == as) { // Expand table unless stale
// 两倍扩容
Cell[] rs = new Cell[n << 1];
for (int i = 0; i < n; ++i)
rs[i] = as[i];
cells = rs;
}
} finally {
cellsBusy = 0;
}
collide = false;
continue; // Retry with expanded table
}
// 不扩容的话,或者扩容成功,需要重新分配槽位
h = advanceProbe(h);
}
// 2. cells未被初始化,尝试获取锁
else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
boolean init = false;
try { // Initialize table
// 双检锁,保证确定没有初始化,
if (cells == as) {
// 初始的cells大小为2,并且所有的槽位cell都是懒惰式,使用时才会进行创建
Cell[] rs = new Cell[2];
rs[h & 1] = new Cell(x);
cells = rs;
init = true;
}
} finally {
cellsBusy = 0;
}
// 初始化创建成功会直接结束该方法,否则基于自旋,寻找对应的槽位累加
if (init)
break;
}
// 3. 初始化失败,存在初始化的竞争,直接尝试累加到base
else if (casBase(v = base, ((fn == null) ? v + x :
fn.applyAsLong(v, x))))
break; // Fall back on using base
}
}
ArrayBlockingQueue
主要使用了 ReentrantLock 通过其创立 Condition 实现 take 和 put 的协同并发安全操作。
items 、takeIndex 、putIndex 、count 等都是临界区资源,加锁以保证并发的安全性
private static final long serialVersionUID = -817911632652898426L;
/** The queued items */
final Object[] items;
/** items index for next take, poll, peek or remove */
int takeIndex;
/** items index for next put, offer, or add */
int putIndex;
/** Number of elements in the queue */
int count;
/*
* Concurrency control uses the classic two-condition algorithm * found in any textbook. */
/** Main lock guarding all access */
final ReentrantLock lock;
/** Condition for waiting takes */
private final Condition notEmpty;
/** Condition for waiting puts */
private final Condition notFull;
/**
* Inserts element at current put position, advances, and signals.
* Call only when holding lock.
* 入队操作,获取锁后直接在对应生产者指针部分设置值
*/
private void enqueue(E x) {
// assert lock.getHoldCount() == 1;
// assert items[putIndex] == null; final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal();
}
/**
* Extracts element at current take position, advances, and signals.
* Call only when holding lock.
* 消费操作,需要关注自定义的迭代器
*/
private E dequeue() {
// assert lock.getHoldCount() == 1;
// assert items[takeIndex] != null; final Object[] items = this.items;
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex];
items[takeIndex] = null;
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
notFull.signal();
return x;
}
/**
* Creates an {@code ArrayBlockingQueue} with the given (fixed) * capacity and the specified access policy.
*
* @param capacity the capacity of this queue
* @param fair if {@code true} then queue accesses for threads blocked
* on insertion or removal, are processed in FIFO order;
* if {@code false} the access order is unspecified.
* @throws IllegalArgumentException if {@code capacity < 1}
*/
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
/**
* Inserts the specified element at the tail of this queue, waiting * for space to become available if the queue is full.
*
* @throws InterruptedException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
lock.unlock();
}
}
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}}
CopyOnWriteArrayList
该并发容器适用于 读多写少 的场景,因为内部的写操作实现为写时复制操作,而读操作不需要进行加锁 处理,可以使得读操作有极高的响应速度。但是同样的,因为在写操作时先复制原有数组到新数组然后改动,最后赋值会原数组,这一段过程虽然加锁,但是存在一种情况:
- 先调用写操作,但是写操作还在执行过程中
- 调用读操作,但是读到的是旧数据,写操作可能还在进行数组的复制
- 返回旧数据,同时写操作完成 上述的情况就会导致短期的数据不一致问题,但是会快速反应给读操作。
@SuppressWarnings("unchecked")
private E get(Object[] a, int index) {
return (E) a[index];
}
/**
* {@inheritDoc}
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
return get(getArray(), index);
}
/**
* Replaces the element at the specified position in this list with the
* specified element.
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E set(int index, E element) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
E oldValue = get(elements, index);
if (oldValue != element) {
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len);
newElements[index] = element;
setArray(newElements);
} else {
// Not quite a no-op; ensures volatile write semantics
setArray(elements);
} return oldValue;
} finally {
lock.unlock();
}}
CountDownLatch
闭锁用于实现一扇门,阻止线程通过,直到其到达最终状态,不可重复使用。
其具体实现就是通过自定义一个同步器类,继承至 AQS 实现一个共享锁,后续 countDown 就是减去获取到的共享锁,而 await 用于争抢一个共享锁
/**
* Causes the current thread to wait until the latch has counted down to
* zero, unless the thread is {@linkplain Thread#interrupt interrupted}.
*
* <p>If the current count is zero then this method returns immediately.
*
* <p>If the current count is greater than zero then the current
* thread becomes disabled for thread scheduling purposes and lies
* dormant until one of two things happen:
* <ul>
* <li>The count reaches zero due to invocations of the
* {@link #countDown} method; or
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread.
* </ul>
*
* <p>If the current thread:
* <ul>
* <li>has its interrupted status set on entry to this method; or
* <li>is {@linkplain Thread#interrupt interrupted} while waiting,
* </ul>
* then {@link InterruptedException} is thrown and the current thread's
* interrupted status is cleared.
*
* @throws InterruptedException if the current thread is interrupted
* while waiting
*/
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
/**
* Decrements the count of the latch, releasing all waiting threads if
* the count reaches zero.
*
* <p>If the current count is greater than zero then it is decremented.
* If the new count is zero then all waiting threads are re-enabled for
* thread scheduling purposes.
*
* <p>If the current count equals zero then nothing happens.
*/
public void countDown() {
sync.releaseShared(1);
}
CycleBarrier
栅栏是一种类似于闭锁的对象,可以实现阻塞一组线程,直到某个事件的发生,但是不同的是它可以实现一个线程可以等待其他线程,而闭锁是直接同步到达。并且该栅栏可以重复使用。
// 示例,实现一组线程互相等待,直到所有线程执行完毕就执行接下来的任务,若有一个失败,全部都会失败
class Solver {
final int N;
final float[][] data;
final CyclicBarrier barrier;
class Worker implements Runnable {
int myRow;
Worker(int row) { myRow = row; }
public void run() {
while (!done()) {
processRow(myRow);
try {
barrier.await();
} catch (InterruptedException ex) {
return;
} catch (BrokenBarrierException ex) {
return;
}
}
}
}
public Solver(float[][] matrix) {
data = matrix;
N = matrix.length;
Runnable barrierAction =
new Runnable() { public void run() { mergeRows(...); }};
barrier = new CyclicBarrier(N, barrierAction);
List<Thread> threads = new ArrayList<Thread>(N);
for (int i = 0; i < N; i++) {
Thread thread = new Thread(new Worker(i));
threads.add(thread);
thread.start();
}
// wait until done
for (Thread thread : threads)
thread.join();
}
}
具体实现:使用一个 ReentrantLock 和 Condition 共同实现对线程的阻塞:
一共有几个变量需要关注:count 参与者数量,barrierCommand 所有线程完成后需要执行的任务
ReentrantLock 和 trip 用于协调线程之间的运行关系。generation 用于表示每一代,可以实现循环使用
在这里使用加锁操作,保证 count 和 broken 屏障状态的更新原子性。
flowchart TB
A["执行await()"]
B["获取锁lock"]
C["count--(原子操作)"]
D["进入等待队列trip"]
E{"最后一个任务"}
F["执行屏障任务"]
G["下一代屏障,唤醒所有等待的线程"]
A-->B
B-->C
C-->E
E--不是最后一个-->D
E--最后一个任务-->F
F-->G
/**
* 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();
}}