Condition初解
public interface Lock {
//返回绑定到此Lock实例的新Condition实例。 用于实现线程间的通信
//类似于 synchronized 调用 Object的wait()和notify()/notifyAll() 方法
Condition newCondition();
}
//Condition接口
public interface Condition {
/**
* 使当前线程等待,直到发出信号或 中断。
* 与此 Condition 相关的锁以原子方式释放,当前线程因线程调度目的而被禁用并处于休眠状态,直到发生以下四种情况 之一 :
* 其他一些线程为此Condition调用了该signal方法,而当前线程恰好被选为要唤醒的线程;
* 其他一些线程为此Condition调用该signalAll方法;
* 其他一些线程会中断当前线程,并且支持线程挂起的中断 ;
* 发生“虚假唤醒”。
* 在所有情况下,在此方法返回之前,当前线程必须重新获取与此条件关联的锁。当线程返回时,它 保证 保持此锁。
* 如果当前线程:
* 在进入此方法时设置了中断状态;或
* 在等待时被中断,并支持线程挂起的 中断 ,
* 然后 InterruptedException 被抛出,当前线程的中断状态被清除。在第一种情况下,没有指定是否在释放锁之前进行中断测试。
*/
void await() throws InterruptedException;
/**
* 使当前线程等待,直到发出信号。
* 根据上一个方法相比较、不支持中断
*/
void awaitUninterruptibly();
/**
* 使当前线程等待,直到发出信号或中断,或者经过指定的等待时间。
*/
long awaitNanos(long nanosTimeout) throws InterruptedException;
/**
* 使当前线程等待,直到发出信号或中断,或者经过指定的等待时间。此方法在行为上等效于:
* awaitNanos(unit.toNanos(time)) > 0
*/
boolean await(long time, TimeUnit unit) throws InterruptedException;
/**
* 使当前线程等待,直到发出信号或中断,或者指定的截止时间过去。
*/
boolean awaitUntil(Date deadline) throws InterruptedException;
/**
* 唤醒一个等待线程。
* 如果有任何线程正在等待此条件,则选择一个线程进行唤醒。然后,该线程必须重新获取锁,然后才能从 await返回。
* 注意事项
* 可能(并且通常确实)要求当前线程在调用此方法时持有与此 Condition 关联的锁。实现必须记录此前提条件以及未保持锁时采取的任何操作。通常, * IllegalMonitorStateException 将引发异常。
*/
void signal();
/**
* 唤醒所有等待线程。
* 如果有任何线程正在等待这种情况,则它们都将被唤醒。每个线程必须先重新获取锁,然后才能从 await返回。
* 注意事项
* 可能(并且通常确实)要求当前线程在调用此方法时持有与此 Condition 关联的锁。实现必须记录此前提条件以及未保持锁时采取的任何操作。通常, * IllegalMonitorStateException 将引发异常。
*/
void signalAll();
}
AQS中Condition的实现
public class ConditionObject implements Condition, java.io.Serializable {
private static final long serialVersionUID = 1173984872572414699L;
/** First node of condition queue. */
private transient Node firstWaiter;
/** Last node of condition queue. */
private transient Node lastWaiter;
/**
* Creates a new {@code ConditionObject} instance.
*/
public ConditionObject() { }
}
AQS中的ConditionObject实现了Condition接口,ConditionObject维护了一个NODE的单向链表,NODE使用的是AQS中定义的NODE节点,NODE的默认状态为Node.CONDITION(-2)
通过ReentrantLock解析AQS实现Condition的具体细节
//实现了lock接口的方法
public Condition newCondition() {
return sync.newCondition();
}
final ConditionObject newCondition() {
//返回一个ConditionObject示例
return new ConditionObject();
}
ConditionObject.await() throws InterruptedException
public final void await() throws InterruptedException {
//判断当前线程是否是中断状态
if (Thread.interrupted())
throw new InterruptedException();
//向ConditionObject维护的单向链表中增加一个节点
Node node = addConditionWaiter();
//在调用此方法时当前线程持有锁,释放当前线程持有的所有锁
int savedState = fullyRelease(node);
int interruptMode = 0;
//自旋 如果当前节点不在等待的同步队列中
while (!isOnSyncQueue(node)) {
//挂起当前线程 如果当前线程设置了中断标识 则会直接唤醒 sleep join wait 方法设置了中断则会直接抛出异常
//设置了中断的线程不会被挂起
LockSupport.park(this);
//检查该线程的中断时机(判断是中断唤醒了线程还是signal唤醒的当前线程) 返回中断模式
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
//获取队列尝试加锁 在等待过程中中断了 并且中断不是抛出异常 是重新中断
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
//向ConditionObject维护的双向链表中增加一个节点 ConditionObject方法
private Node addConditionWaiter() {
//最后一个等待节点
Node t = lastWaiter;
// If lastWaiter is cancelled, clean out.
if (t != null && t.waitStatus != Node.CONDITION) {
//如果最后一个节点不是条件等待状态,移除队列中的所有取消状态节点
unlinkCancelledWaiters();
t = lastWaiter;
}
//创建一个新节点 线程信息为当前线程 状态为等待状态-2
Node node = new Node(Thread.currentThread(), Node.CONDITION);
//并将该节点放在队列的末尾
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node;
lastWaiter = node;
//返回当前节点
return node;
}
//断开所有取消状态的等待者 ConditionObject方法
private void unlinkCancelledWaiters() {
//第一个节点
Node t = firstWaiter;
Node trail = null;
while (t != null) {
Node next = t.nextWaiter;
if (t.waitStatus != Node.CONDITION) {
t.nextWaiter = null;
if (trail == null)
firstWaiter = next;
else
trail.nextWaiter = next;
if (next == null)
lastWaiter = trail;
}
else
trail = t;
t = next;
}
}
//释放当前线程持有的所有锁 会唤起位于head下一个等待的线程节点 AQS方法
final int fullyRelease(Node node) {
boolean failed = true;
try {
//获取状态如果重入了锁状态大于1
int savedState = getState();
//释放锁
if (release(savedState)) {
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed)
//释放锁失败,当前节点状态改为取消
node.waitStatus = Node.CANCELLED;
}
}
//如果最初放置在条件队列上的节点(始终是节点)现在正在等待在同步队列上重新获取,则返回 true。 AQS方法
//判断当前节点是否在需要排队的同步队列中
final boolean isOnSyncQueue(Node node) {
//如果节点状态为条件等待 或者prev == null 则不在队列中
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
//如果有下一节点表明在队列中
if (node.next != null) // If has successor, it must be on queue
return true;
/*
* node.prev can be non-null, but not yet on queue because
* the CAS to place it on queue can fail. So we have to
* traverse from tail to make sure it actually made it. It
* will always be near the tail in calls to this method, and
* unless the CAS failed (which is unlikely), it will be
* there, so we hardly ever traverse much.
*/
//在队列中从尾部去查当前节点
return findNodeFromTail(node);
}
//如果节点通过从尾部向后搜索在同步队列上,则返回 true。仅当 isOnSyncQueue 需要时才调用。
private boolean findNodeFromTail(Node node) {
Node t = tail;
for (;;) {
if (t == node)
return true;
if (t == null)
return false;
t = t.prev;
}
}
//检查中断,如果在发出信号之前中断,则返回 THROW_IE,如果在发出信号后返回 REINTERRUPT,如果未中断,则返回 0。
private int checkInterruptWhileWaiting(Node node) {
return Thread.interrupted() ?
//发出信号之前中断了 则返回中断抛出异常模式
(transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) : 0;
}
//如有必要,传输节点以在取消等待后同步队列。如果线程在发出信号之前被取消,则返回 true。
//取消等待后转移
final boolean transferAfterCancelledWait(Node node) {
//如果节点的状态从条件等待改为了默认 将该节点加入到同步队列尾部,如果获取到锁则执行
//signal 方法唤醒线程会设置当前线程的ws为0 如果此方法成功则说明 当前线程在发出信号之前中断了
if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
enq(node);
return true;
}
/*
* If we lost out to a signal(), then we can't proceed
* until it finishes its enq(). Cancelling during an
* incomplete transfer is both rare and transient, so just
* spin.
*/
//如果唤醒之后中断了 如果此线程没在同步队列中 这放弃当前cpu 直到被放到同步队列中
while (!isOnSyncQueue(node))
Thread.yield();
return false;
}
//引发 InterruptedException、重新中断当前线程或不执行任何操作,具体取决于模式
private void reportInterruptAfterWait(int interruptMode)
throws InterruptedException {
if (interruptMode == THROW_IE)
throw new InterruptedException();
else if (interruptMode == REINTERRUPT)
selfInterrupt();
}
ConditionObject.awaitUninterruptibly()
//使一个线程等待不会响应中断
public final void awaitUninterruptibly() {
//将当前线程节点添加到条件等待队列中
Node node = addConditionWaiter();
//释放锁
int savedState = fullyRelease(node);
boolean interrupted = false;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
//如果被中断标识唤醒(清除中断标识)防止在重新获取锁的过程中无法挂起当前线程 则记录中断标识
if (Thread.interrupted())
interrupted = true;
}
//如果中断了则标识当前线程为中断状态
if (acquireQueued(node, savedState) || interrupted)
selfInterrupt();
}
ConditionObject.awaitNanos(long nanosTimeout) throws InterruptedException
实现定时条件等待。
1如果当前线程中断,则抛出 InterruptedException。
2保存 返回的 getState锁定状态。
3使用保存的状态作为参数进行调用 release ,如果失败,则抛出 IllegalMonitorStateException。
4阻塞,直到发出信号、中断或超时。
5通过调用 with saved state 作为参数的 acquire 专用版本来重新获取。
6如果在步骤 4 中被阻止时中断,则引发 InterruptedException。
public final long awaitNanos(long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
//计算等待超时时间点
final long deadline = System.nanoTime() + nanosTimeout;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
//等待时间为负数 表示等待已经超时 尝试将节点加入到同步队列 或者被signal通知加入到同步队列
if (nanosTimeout <= 0L) {
transferAfterCancelledWait(node);
break;
}
//根据spinForTimeoutThreshold判断是需要挂起还是自旋
if (nanosTimeout >= spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
//重新赋值剩余等待时间
nanosTimeout = deadline - System.nanoTime();
}
//在同步队列中尝试获取锁 启动该线程
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
//该值的 nanosTimeout 估计值减去从此方法返回后等待所花费的时间。正值可以用作后续调用此方法的参数,以完成等待所需 时间。小于或等于零的值表示没有剩余时间
return deadline - System.nanoTime();
}
ConditionObject.await(long time, TimeUnit unit) throws InterruptedException
实现定时条件等待。
1如果当前线程中断,则抛出 InterruptedException。
2保存 返回的 getState锁定状态。
3使用保存的状态作为参数进行调用 release ,如果失败,则抛出 IllegalMonitorStateException。
4阻塞,直到发出信号、中断或超时。
5通过调用 with saved state 作为参数的 acquire 专用版本来重新获取。
6如果在步骤 4 中被阻止时中断,则引发 InterruptedException。
7如果在步骤 4 中被阻止时超时,则返回 false,否则为 true。
public final boolean await(long time, TimeUnit unit)
throws InterruptedException {
long nanosTimeout = unit.toNanos(time);
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
final long deadline = System.nanoTime() + nanosTimeout;
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
timedout = transferAfterCancelledWait(node);
break;
}
if (nanosTimeout >= spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return !timedout;
}
ConditionObject.awaitUntil(Date deadline) throws InterruptedException
实现绝对定时条件等待。
1如果当前线程中断,则抛出 InterruptedException。
2保存 返回的 getState锁定状态。
3使用保存的状态作为参数进行调用 release ,如果失败,则抛出 IllegalMonitorStateException。
4阻塞,直到发出信号、中断或超时。
5通过调用 with saved state 作为参数的 acquire 专用版本来重新获取。
6如果在步骤 4 中被阻止时中断,则引发 InterruptedException。
7如果在步骤 4 中被阻止时超时,则返回 false,否则为 true。
public final boolean awaitUntil(Date deadline)
throws InterruptedException {
long abstime = deadline.getTime();
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (System.currentTimeMillis() > abstime) {
timedout = transferAfterCancelledWait(node);
break;
}
LockSupport.parkUntil(this, abstime);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return !timedout;
}
ConditionObject.signal()
//唤醒该条件下的一个线程
public final void signal() {
//判断执行通知的线程是不是当前持有锁的线程
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
//条件等待队列中的第一个等待者
Node first = firstWaiter;
if (first != null)
//执行通知
doSignal(first);
}
//如果以独占方式保持同步则为true 否则为false ReentrantLock的sync重写了AQS的方法
//默认实现抛出 UnsupportedOperationException.此方法仅在方法内部 AbstractQueuedSynchronizer.ConditionObject 调 用,因此,如果不使用条件,则无需定义此方法。
protected final boolean isHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
}
//
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
//如果将first放入同步队列失败 并且还有下一个条件节点则唤醒下一个
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
//将节点从条件队列传输到同步队列。如果成功,则返回 true。
final boolean transferForSignal(Node node) {
/*
* If cannot change waitStatus, the node has been cancelled.
*/
//如果没有赋值成功表示此node节点线程被中断唤醒已经是处于取消状态
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
//拼接到队列并尝试设置 Predecessor 的 waitStatus 以指示线程(可能)正在等待。如果取消或尝试设置 waitStatus 失败, 请唤醒以重新同步(在这种情况下,waitStatus 可能是暂时且无害的错误)。
//将此条件节点放到同步节点尾部 返回的是node的前一节点
Node p = enq(node);
int ws = p.waitStatus;
//如果前一节点处于取消状态 或者SIGNAL状态没有赋值成功则直接唤醒该节点线程
//如果前一线程为Node.SIGNAL则等待前一线程 唤醒此线程
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
ConditionObject.signalAll()
//唤醒所有等待线程
public final void signalAll() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignalAll(first);
}
private void doSignalAll(Node first) {
//将条件队列 清空
lastWaiter = firstWaiter = null;
do {
Node next = first.nextWaiter;
first.nextWaiter = null;
//循环将所有的条件节点同步到同步队列中
transferForSignal(first);
first = next;
} while (first != null);
}