/** * Adds a new waiter to wait queue. * 在等待队列中添加一个新的waiter。 * * @return its new wait node 它的新等待节点 */ private Node addConditionWaiter() { //保存条件队列的最后一个节点。 Nodet= lastWaiter; // If lastWaiter is cancelled, clean out. //如果lastWaiter被取消,请清理。 if (t != null && t.waitStatus != Node.CONDITION) { //从条件队列中取消已取消的Waiter节点的链接 unlinkCancelledWaiters(); t = lastWaiter; } //新节点 Nodenode=newNode(Thread.currentThread(), Node.CONDITION); //如果当前等待队列中没有节点,则node为新的首哨兵 if (t == null) firstWaiter = node; else //指针连接 t.nextWaiter = node; //尾哨兵移动到node lastWaiter = node; return node; } /** * Unlinks cancelled waiter nodes from condition queue. * Called only while holding lock. This is called when * cancellation occurred during condition wait, and upon * insertion of a new waiter when lastWaiter is seen to have * been cancelled. This method is needed to avoid garbage * retention in the absence of signals. So even though it may * require a full traversal, it comes into play only when * timeouts or cancellations occur in the absence of * signals. It traverses all nodes rather than stopping at a * particular target to unlink all pointers to garbage nodes * without requiring many re-traversals during cancellation * storms. * 从条件队列中取消已取消的服务员节点的链接。仅在持锁时调用。 * 当在条件等待期间发生取消时调用此函数,当看到lastWaiter已被取消时调用新waiter。 * 在没有信号的情况下,需要使用这种方法来避免垃圾保留。 * 因此,尽管它可能需要一个完整的遍历,但只有在没有信号的情况下超时或取消才会起作用。 * 它遍历所有节点,而不是停在一个特定的目标上,以断开到垃圾节点的所有指针的链接 * ,而不需要在取消风暴期间进行多次重新遍历。 */ privatevoidunlinkCancelledWaiters() { Nodet= firstWaiter; Nodetrail=null; //迭代等待队列,只要ws不为CONDITION,就移除节点 while (t != null) { //保存当前节点的下一个节点 Nodenext= t.nextWaiter; //ws不为CONDITION,准备移除此节点 if (t.waitStatus != Node.CONDITION) { //当前节点的后继置空,GC t.nextWaiter = null; //最开始,trail为null,首哨兵指向当前节点的下一个节点 if (trail == null) firstWaiter = next; else trail.nextWaiter = next; //如果已经没有后继节点 if (next == null) //尾哨兵指向最后一个等待条件节点 lastWaiter = trail; } else //trail指向当前等待条件节点 trail = t; //后移 t = next; } }
/** * Invokes release with current state value; returns saved state. * Cancels node and throws exception on failure. * 使用当前状态值调用release;返回保存的状态。取消节点并在失败时抛出异常。 * * @param node the condition node for this wait * @return previous sync state */ finalintfullyRelease(Node node) { booleanfailed=true; try { //返回同步状态的当前值 intsavedState= getState(); //释放锁 if (release(savedState)) { //锁释放成功 failed = false; return savedState; } else { thrownewIllegalMonitorStateException(); } } finally { if (failed) //锁释放失败的时候,将节点的ws设置为取消状态 node.waitStatus = Node.CANCELLED; } } /** * Releases in exclusive mode. Implemented by unblocking one or * more threads if {@link #tryRelease} returns true. * This method can be used to implement method {@link Lock#unlock}. * 以独占模式释放,如果{@link #tryRelease}返回true,则通过解阻塞一个或多个线程来实现。 * 此方法可用于实现方法{@link Lock#unlock}。 * * @param arg the release argument. This value is conveyed to * {@link #tryRelease} but is otherwise uninterpreted and * can represent anything you like. * @return the value returned from {@link #tryRelease} */ publicfinalbooleanrelease(int arg) { //由子类实现 if (tryRelease(arg)) { Nodeh= head; if (h != null && h.waitStatus != 0) //唤醒node的后继节点(如果存在的话)。 unparkSuccessor(h); returntrue; } returnfalse; } /** * 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); }
/** * Returns true if a node, always one that was initially placed on * a condition queue, is now waiting to reacquire on sync queue. * 如果一个节点(始终是最初放置在条件队列中的节点)现在正等待在同步队列上重新获取,则返回true。 * * @param node the node * @return true if is reacquiring */ finalbooleanisOnSyncQueue(Node node) { if (node.waitStatus == Node.CONDITION || node.prev == null) returnfalse; if (node.next != null) // If has successor, it must be on queue returntrue; /* * node.prev can be non-null, but not yet on queue because * the CAS to place it on queue can fail. So we have to * traverse from tail to make sure it actually made it. It * will always be near the tail in calls to this method, and * unless the CAS failed (which is unlikely), it will be * there, so we hardly ever traverse much. * 从后向前查找节点是否存在此同步队列 */ return findNodeFromTail(node); } /** * Returns true if node is on sync queue by searching backwards from tail. * Called only when needed by isOnSyncQueue. * * @return true if present */ privatebooleanfindNodeFromTail(Node node) { //从后向前遍历 Nodet= tail; for (; ; ) { if (t == node) returntrue; if (t == null) returnfalse; t = t.prev; } }
/** * Checks for interrupt, returning THROW_IE if interrupted * before signalled, REINTERRUPT if after signalled, or * 0 if not interrupted. * 检查是否有中断,如果在信号之前中断,返回THROW_IE;如果在信号之后中断, * 返回REINTERRUPT;如果没有中断,返回0。 */ privateintcheckInterruptWhileWaiting(Node node) { return Thread.interrupted() ? (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) : 0; } /** * Transfers node, if necessary, to sync queue after a cancelled wait. * Returns true if thread was cancelled before being signalled. * 如果需要,在取消等待后传输节点来同步队列。如果线程在发出信号之前被取消,则返回true。 * * @param node the node * @return true if cancelled before the node was signalled */ finalbooleantransferAfterCancelledWait(Node node) { if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) { enq(node); returntrue; } /* * If we lost out to a signal(), then we can't proceed * until it finishes its enq(). Cancelling during an * incomplete transfer is both rare and transient, so just * spin. * 如果我们被signal()取代,那么我们就不能继续,直到它完成它的enq()。 * 在一个不完整的转移过程中取消是罕见的,也是短暂的,所以只要旋转。 */ while (!isOnSyncQueue(node)) //释放CUP Thread.yield(); returnfalse; } /** * Throws InterruptedException, reinterrupts current thread, or * does nothing, depending on mode. * 抛出InterruptedException,重新中断当前线程,或者什么都不做,这取决于模式。 */ privatevoidreportInterruptAfterWait(int interruptMode) throws InterruptedException { if (interruptMode == THROW_IE) thrownewInterruptedException(); elseif (interruptMode == REINTERRUPT) selfInterrupt(); }
唤醒signal()
只有获取锁的线程,才能执行这个方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/** * 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; }