一、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" />