/** * Moves the longest-waiting thread, if one exists, from the * wait queue for this condition to the wait queue for the * owning lock. * 将等待时间最长的线程(如果存在的话)从该条件的等待队列移动到拥有锁的等待队列。 * * @throws IllegalMonitorStateException if {@link #isHeldExclusively} * returns {@code false} */ publicfinalvoidsignal() { //如果仅针对当前(调用)线程保持同步,则返回true。 //没有拿到锁的线程,不能调用此方法 if (!isHeldExclusively()) thrownewIllegalMonitorStateException(); //等待时间最长的线程,队首 Nodefirst= firstWaiter; if (first != null) // 将节点从条件队列传输到同步队列,唤醒 doSignal(first); } /** * Removes and transfers nodes until hit non-cancelled one or * null. Split out from signal in part to encourage compilers * to inline the case of no waiters. * 删除和传输节点,直到到达不可取消的或null。 * 从signal中分离出来,部分原因是为了鼓励编译器在没有等待器的情况下内联。 * * @param first (non-null) the first node on condition queue 条件队列上的第一个节点 */ privatevoiddoSignal(Node first) { //循环,直到将节点从条件队列传输到同步队列返回false 和 条件队列上的第一个节点不为空。 do { //向后移动一次首哨兵,如果当前首哨兵所在节点为空,则将尾哨兵设为空 if ((firstWaiter = first.nextWaiter) == null) lastWaiter = null; //断开第一个节点与后继节点之间的关系 first.nextWaiter = null; } while (!transferForSignal(first) && (first = firstWaiter) != null); } /** * Transfers a node from a condition queue onto sync queue. * Returns true if successful. * 将节点从条件队列传输到同步队列。如果成功返回true。 * * @param node the node * @return true if successfully transferred (else the node was * cancelled before signal) */ finalbooleantransferForSignal(Node node) { /* * If cannot change waitStatus, the node has been cancelled. * 如果无法更改等待状态,则节点已被取消。 */ if (!compareAndSetWaitStatus(node, Node.CONDITION, 0)) returnfalse;
/* * Splice onto queue and try to set waitStatus of predecessor to * indicate that thread is (probably) waiting. If cancelled or * attempt to set waitStatus fails, wake up to resync (in which * case the waitStatus can be transiently and harmlessly wrong). * 将Splice连接到队列,并尝试设置前辈的等待状态,以指示线程(可能)正在等待。、 * 如果取消或尝试设置等待状态失败,则唤醒并重新同步 * (在这种情况下,等待状态可能是暂时错误的,并且不会造成任何危害)。 */ Nodep= enq(node); intws= p.waitStatus; //节点的CAS等待状态字段。 if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL)) //解阻塞 LockSupport.unpark(node.thread); returntrue; }