提供类似Object的wait/notify功能,搭配显式锁Lock使用
创建Condition是每个锁的基本功能,一个Condition相当于在锁上开辟了一个条件等待队列
Lock.java1 2 3 4
| public interface Lock { Condition newCondition(); }
|
Condition依赖Lock,在操作前必须获得锁
唤醒条件
- 其他线程在Condition上调用了signal或signalAll主动唤醒
- 其他线程在线程上调用中断
- 无原因错误唤醒
Condition.java1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public interface Condition { void await() throws InterruptedException; void awaitUninterruptibly(); long awaitNanos(long nanosTimeout) throws InterruptedException; boolean await(long time, TimeUnit unit) throws InterruptedException; boolean awaitUntil(Date deadline) throws InterruptedException;
void signal(); void signalAll(); }
|
和wait/notify类似,由于存在错误唤醒,需要包围循环检查逻辑
Sample1 2 3 4 5 6 7 8 9
| lock.lock(); try{ while(!condition) { cond.await(); } }finally{ lock.unlock(); }
|
Condition实现
Condition的实现是ConditionObject
它是AQS的内部类,并且是非静态的,因为Condition依附于Lock,因此内部类很合理,并且作为内部类ConditionObject可以操作AQS同步队列
- 使用Condition需要获得锁,利用AQS中的同步队列
- 多个线程等待在同一Condition上,因此Condition自身维护等待队列
用于同步的节点结构和用于条件等待的节点结构是共享的, 使用上有细微区别,条件等待队列是单链表并且维护节点状态,而同步队列是双链表
AbstractQueuedSynchronizer.java1 2 3 4 5 6 7 8 9 10
| public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
public class ConditionObject implements Condition, java.io.Serializable { private transient Node firstWaiter; private transient Node lastWaiter;
}
|
创建Condition过程交给AQS实现类,即内部类内使用new获取实例,以重入锁为例
ReentrantLock.java1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class ReentrantLock implements Lock, java.io.Serializable { private final Sync sync;
public Condition newCondition() { return sync.newCondition(); }
abstract static class Sync extends AbstractQueuedSynchronizer { final ConditionObject newCondition() { return new ConditionObject(); } } }
|
等待过程,大体逻辑是进入条件等待队列等待,等到进入同步队列后重新参与锁竞争
AbstractQueuedSynchronizer$ConditionObject.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| public final void await() throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); Node node = addConditionWaiter(); int savedState = fullyRelease(node); int interruptMode = 0;
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) unlinkCancelledWaiters(); if (interruptMode != 0) reportInterruptAfterWait(interruptMode); }
private Node addConditionWaiter() { Node t = lastWaiter; 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; }
|
唤醒过程,大体逻辑是在条件等待队列中,选取一个还没取消的,转移到同步队列参与锁竞争
AbstractQueuedSynchronizer$ConditionObject.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| 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) { if (!compareAndSetWaitStatus(node, Node.CONDITION, 0)) return false; Node p = enq(node); int ws = p.waitStatus; if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL)) LockSupport.unpark(node.thread); return true; }
private Node enq(final Node node) { for (;;) { Node t = tail; if (t == null) { if (compareAndSetHead(new Node())) tail = head; } else { node.prev = t; if (compareAndSetTail(t, node)) { t.next = node; return t; } } } } }
|
总结
- Condition本身没有条件,条件是外围业务逻辑控制,Condition作用是开辟一个条件等待队列
- 线程本身是参与锁竞争的,由于不满足条件无法继续执行,外围逻辑调用await把线程放入条件等待队列等待,等到满足条件外围调用signal后加入同步队列重新参与锁竞争
- Object有一个同步队列(加锁队列)和一个等待队列(wait-notify),而Lock可以包含多个Condition,即能维护多个等待队列
- Condition底层实现基于LockSupport.park