signal方法
只是将条件列表中的头节点,放入琐池同步队列中,其他等待线程依旧等待
获取头结点
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
// 首先获取头节点
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
将头结点的指向设置成null从而从条件链表中删除
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 cannot change waitStatus, the node has been cancelled.
*/
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;
}
(ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
这段代码是为了确保当前节点 node
能够根据前驱节点 p
的状态正确地进行下一步操作。如果前驱节点 p
不再有效(被取消)或者无法将其状态设置为 SIGNAL
,则当前节点对应的线程将被唤醒,以便它能够重新检查等待队列的状态并采取适当的行动。这是AQS处理同步和条件等待时的重要部分,确保线程在等待时能够正确响应各种变化