一、Condition的观念
回想 synchronized 要害字,它共同 Object 的 wait()、notify() 系列要领可以实现期待/通知模式。
对付 Lock,通过 Condition 也可以实现期待/通知模式。
Condition 是一个接口。
Condition 接口的实现类是 Lock(AQS)中的 ConditionObject。
Lock 接口中有个 newCondition() 要领,通过这个要领可以得到 Condition 工具(其实就是 ConditionObject)。
因此,通过 Lock 工具可以得到 Condition 工具。
Lock lock = new ReentrantLock(); Condition c1 = lock.newCondition(); Condition c2 = lock.newCondition();
二、Condition的实现阐明
ConditionObject 类是 AQS 的内部类,实现了 Condition 接口。
public class ConditionObject implements Condition, java.io.Serializable { private transient Node firstWaiter; private transient Node lastWaiter; ...
可以看到,劳务派遣管理系统,期待行列和同部行列一样,昆山软件开发,利用的都是同步器 AQS 中的节点类 Node。
同样拥有首节点和尾节点,
每个 Condition 工具都包括着一个 FIFO 行列。
布局图:
劳务调派信息打点系统 while 说明节点已经在同部行列中" class="aligncenter size-full wp-image-30151" title="condition" src="/uploads/allimg/c181010/153911553c0R0-13F1.jpg" />
挪用 Condition 的 await() 要了解使线程进入期待行列,并释放锁,线程状态变为期待状态。
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) // clean up if cancelled unlinkCancelledWaiters(); if (interruptMode != 0) reportInterruptAfterWait(interruptMode); }
阐明上述要领的或许进程:
劳务调派信息打点系统 while 说明节点已经在同部行列中" class="aligncenter size-full wp-image-30152" title="enterCon" src="/uploads/allimg/c181010/153911553c40F-24631.png" />
addConditionWaiter() 要领:
private Node addConditionWaiter() { Node t = lastWaiter; if (t != null && t.waitStatus != Node.CONDITION) { //排除条件行列中所有状态不为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; }
进程阐明:同部行列的首节点移动到期待行列。插手尾节点之前会排除所有状态不为 Condition 的节点。
挪用 Condition 的 signal() 要领,可以叫醒期待行列的首节点(期待时间最长),叫醒之前会将该节点移动到同部行列中。
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; //假如结点p的状态为cancel 可能修改waitStatus失败,则直接叫醒 if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL)) LockSupport.unpark(node.thread); return true; }
挪用同步器的 enq 要领,劳务派遣管理系统,将节点移动到同部行列,
满意条件后利用 LockSupport 叫醒该线程。
劳务调派信息打点系统 while 说明节点已经在同部行列中" class="aligncenter size-full wp-image-30153" title="signalcon" src="/uploads/allimg/c181010/153911553cU30-39107.png" />