条件变量Condition
Condition实现了synchronized同步器的wait/notify/notifyAll的功能,Condition接口提供的API如下:
Condition需要与Lock绑定,一个Lock可以有多个Condition,获取Condition的方式是lock.newCondition()。Condition的实现类在AQS中的ConditionObject,类部维持了一个等待队列:
- 获取Condition
lock.newCondition() -->
// ReentrantLock
public Condition newCondition() {
return sync.newCondition();
}
// ReentrantLock.Sync
final ConditionObject newCondition() {
return new ConditionObject();
}
-->
// AQS.ConditionObject
public ConditionObject() { }
- await()
public final void await() throws InterruptedException {
if (Thread.interrupted()) // 如果当前线程被终端,抛出异常
throw new InterruptedException();
Node node = addConditionWaiter(); // 1. 将当前线程添加到Condition队列
int savedState = fullyRelease(node); // 2. 释放锁
int interruptMode = 0;
while (!isOnSyncQueue(node)) { // 3. 自旋直到被signal或signalAll唤醒
LockSupport.park(this); // 挂起当前线程
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE) // 4. 自旋去获取锁
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
// 1.
private Node addConditionWaiter() {
Node t = lastWaiter;
// If lastWaiter is cancelled, clean out.
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();
t = lastWaiter;
}
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node;
lastWaiter = node;
return node;
}
// 2.
final int fullyRelease(Node node) {
boolean failed = true;
try {
int savedState = getState();
if (release(savedState)) { // 调用release方法释放锁
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed)
node.waitStatus = Node.CANCELLED;
}
}
// 3.
final boolean isOnSyncQueue(Node node) {
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
if (node.next != null) // If has successor, it must be on queue
return true;
return findNodeFromTail(node);
}
private boolean findNodeFromTail(Node node) { // 在sync队列中从尾部到头部查找是不是在sync队列中
Node t = tail;
for (;;) {
if (t == node)
return true;
if (t == null)
return false;
t = t.prev;
}
}
- signal()
public final void signal() {
if (!isHeldExclusively()) // 1. 判断是不是当前线程持有锁,只有持有锁的线程能唤醒其他等待的线程
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first); // 2. 通知Condition队列中的等待最长时间的线程,即firstWaiter
}
// ReentrantLock.Sync
// 1.
protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
// 2.
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) {
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
Node p = enq(node); // 将节点加入sync队列
int ws = p.waitStatus;
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
事例
假设现在有三个线程陆续调用同一个condition的await- 开始状态:thread-1获取锁
-
- thread-1调用await():
用thread-1创建节点,并设置waitStatus= -2(Condition),再将thread-1加入Condition队列,队列为空,将firstWaiter和lastWaiter设为thread-1;调用release释放thread-1拥有的锁,并从Sync队列中移除节点;自旋等待唤醒
- thread-2调用await():
- thread-3调用await():
- 当收到signal信号后,会从condition队列中从头开始将节点移到sync队列,并唤醒自旋获取锁