/** * Releases in shared mode. Implemented by unblocking one or more * threads if {@link #tryReleaseShared} returns true. * * @param arg the release argument. This value is conveyed to * {@link #tryReleaseShared} but is otherwise uninterpreted * and can represent anything you like. * @return the value returned from {@link #tryReleaseShared} */ publicfinalbooleanreleaseShared(int arg) { //子类实现释放锁 if (tryReleaseShared(arg)) { //释放锁 doReleaseShared(); returntrue; } returnfalse; }
/** * Release action for shared mode -- signals successor and ensures * propagation. (Note: For exclusive mode, release just amounts * to calling unparkSuccessor of head if it needs signal.) * 共享模式释放锁 */ privatevoiddoReleaseShared() { /* * Ensure that a release propagates, even if there are other * in-progress acquires/releases. This proceeds in the usual * way of trying to unparkSuccessor of head if it needs * signal. But if it does not, status is set to PROPAGATE to * ensure that upon release, propagation continues. * Additionally, we must loop in case a new node is added * while we are doing this. Also, unlike other uses of * unparkSuccessor, we need to know if CAS to reset status * fails, if so rechecking. */ for (; ; ) { //获取头节点 Nodeh= head; //队列初始化了,且队列中有等待线程节点,即最起码有两个节点 if (h != null && h != tail) { intws= h.waitStatus; //如果头节点的状态时SIGNAL,则需要唤醒其后继节点 if (ws == Node.SIGNAL) { //设置节点状态为0,失败则从新开始循环 if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) continue; // loop to recheck cases //设置成功后,唤醒后继节点 unparkSuccessor(h); } elseif (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) //将头节点状态设置为PROPAGATE continue; // loop on failed CAS } //如果头节点改变了,继续循环 if (h == head) // loop if head changed break; } } /** * Wakes up node's successor, if one exists. * 唤醒node的后继节点(如果存在的话)。 * 释放锁和取消获取锁时被调用 * * @param node the node */ privatevoidunparkSuccessor(Node node) { /* * If status is negative (i.e., possibly needing signal) try * to clear in anticipation of signalling. It is OK if this * fails or if status is changed by waiting thread. * 如果状态为负,清除预期信号,如果此操作失败或状态被等待线程更改,则没有问题。 * CANCELLED = 1 * 0 * SIGNAL = -1 * CONDITION = -2 * PROPAGATE = -3 */ intws= node.waitStatus; if (ws < 0) compareAndSetWaitStatus(node, ws, 0);
/* * Thread to unpark is held in successor, which is normally * just the next node. But if cancelled or apparently null, * traverse backwards from tail to find the actual * non-cancelled successor. * Thread to unpark被保存在后续节点中,它通常只是下一个节点, * 但是,如果取消或明显为空,则从tail向后遍历以找到实际的非取消后继。 */ Nodes= node.next; if (s == null || s.waitStatus > 0) { s = null; //从后向前遍历节点,最后s为离当前节点最近的需要被唤醒的节点 for (Nodet= tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } //唤醒操作 if (s != null) LockSupport.unpark(s.thread); }