/** * Acquires in exclusive mode, ignoring interrupts. Implemented * by invoking at least once {@link #tryAcquire}, * returning on success. Otherwise the thread is queued, possibly * repeatedly blocking and unblocking, invoking {@link * #tryAcquire} until success. This method can be used * to implement method {@link Lock#lock}. * * 在独占模式下获取,忽略中断。 * 通过至少调用一次{@link tryAcquire}并返回成功来实现。 * 否则,线程将排队,并可能反复阻塞和解除阻塞,并调用{@link tryAcquire}直到成功。 * 此方法可用于实现方法{@link Locklock} * * @param arg the acquire argument. This value is conveyed to * {@link #tryAcquire} but is otherwise uninterpreted and * can represent anything you like. * @param arg获取参数。 * 此值会传送到{@link tryAcquire},但否则不会被解释,可以代表您喜欢的任何内容。 */ publicfinalvoidacquire(int arg){ if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
/** * Acquires in exclusive uninterruptible mode for thread already in * queue. Used by condition wait methods as well as acquire. * 以排他的不间断模式获取已在队列中的线程。 * 用于条件等待方法以及获取。 * * @param node the node * @param arg the acquire argument * @return {@code true} if interrupted while waiting */ finalbooleanacquireQueued(final Node node, int arg){ // 标记是否成功获取锁 boolean failed = true; try { // 标记线程等待过程中是否被中断过 boolean interrupted = false; for (;;) { // 拿到前驱节点 final Node p = node.predecessor(); // 如果前驱节点是head,即该节点为老二,那么便有资格去尝试获取锁 if (p == head && tryAcquire(arg)) { // 获取锁成功,当前节点设置成 head setHead(node); // 原 head 节点出队,出队后不存在任何引用,会被GC p.next = null; // help GC // 获取锁成功 failed = false; // 返回是否被中断过 return interrupted; } // 判断获取锁失败后是否可以挂起,如果可以挂起 if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) // 如果线程被中断过,就将 interrupted 标记为 true interrupted = true; } } finally { if (failed) cancelAcquire(node); } }
setHead(node)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/** * Sets head of queue to be node, thus dequeuing. Called only by * acquire methods. Also nulls out unused fields for sake of GC * and to suppress unnecessary signals and traversals. * * 将队列头设置为节点,从而出队。 * 仅通过 acquire 方法调用。 * 出于 GC 和抑制不必要的信号和遍历的目的,还应清空未使用的字段。 * * @param node the node */ privatevoidsetHead(Node node){ head = node; // head指向当前节点 node.thread = null; // 当前节点的 thread 设置为空 node.prev = null; // 当前节点的 头节点设置为空 }
/** * Checks and updates status for a node that failed to acquire. * Returns true if thread should block. This is the main signal * control in all acquire loops. Requires that pred == node.prev. * * 检查并更新无法获取的节点的状态。 * 如果线程应阻塞,则返回true。 * 这是所有采集循环中的主要信号控制。 * 要求 pred == node.prev。 * * @param pred node's predecessor holding status * @param pred 节点的前任保持状态 * @param node the node * @return {@code true} if thread should block * @return {@code true} 如果线程应该阻塞 */ privatestaticbooleanshouldParkAfterFailedAcquire(Node pred, Node node){ // 拿到前驱节点的状态 int ws = pred.waitStatus; if (ws == Node.SIGNAL) // //如果已经告诉前驱拿完号后通知自己一下,那就可以安心休息了 /* * This node has already set status asking a release * to signal it, so it can safely park. * 该节点已经设置了状态,要求释放以发出信号,以便可以安全地停放。 */ returntrue; if (ws > 0) { /* * 如果前驱放弃了,那就一直往前找,直到找到最近一个正常等待的状态,并排在它的后边。 * 注意:那些放弃的结点,由于被自己“加塞”到它们前边, * 它们相当于形成一个无引用链,稍后就会被保安大叔赶走了(GC回收)! */ /* * Predecessor was cancelled. Skip over predecessors and * indicate retry. * 前任已取消。跳过前任并指示重试。 */ do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0); pred.next = node; } else { /* * waitStatus must be 0 or PROPAGATE. Indicate that we * need a signal, but don't park yet. Caller will need to * retry to make sure it cannot acquire before parking. * waitStatus 必须为 0 或 PROPAGATE 。表示我们需要一个信号,但不要停车。 * 呼叫者将需要重试以确保在停车之前无法获取。 */ // 如果前驱正常,那就把前驱的状态设置成SIGNAL,告诉它拿完号后通知自己一下。 // 有可能失败,人家说不定刚刚释放完呢! compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } returnfalse; }
/** * 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 Lockunlock}。 * * @param arg the release argument. This value is conveyed to * {@link #tryRelease} but is otherwise uninterpreted and * can represent anything you like. * @param arg释放参数。 * 该值会传送到{@link tryRelease},但否则不会被解释,可以代表您喜欢的任何内容。 * * @return the value returned from {@link #tryRelease} */ publicfinalbooleanrelease(int arg){ if (tryRelease(arg)) { // 找到头结点 Node h = head; if (h != null && h.waitStatus != 0) // //唤醒等待队列里的下一个线程 unparkSuccessor(h); returntrue; } returnfalse; }
tryRelease(arg)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/** 该方法不比考虑线程安全, * 因为如果有其他线程修改 state 值后, state对该方法是可见的, * 最多不唤醒下一个线程,而是由新的线程获取state的状态 */ protectedfinalbooleantryRelease(int releases){ int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) thrownew IllegalMonitorStateException(); boolean free = false; if (c == 0) { // c = 0 时,代表没有锁(可重入锁计数为0) free = true; setExclusiveOwnerThread(null); } // 设置 state 的状态 setState(c); return free; }
/** * Wakes up node's successor, if one exists. * * @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. * * 如果状态是否定的(即可能需要信号),请尝试清除以预期发出信号。 * 如果失败或等待线程更改状态,则可以。 */ // node一般为当前线程所在的结点。 int ws = 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. * * 释放线程保留在后续线程中,该线程通常只是下一个节点。 * 但是,如果已取消或明显为空,请从尾部向后移动以找到实际的未取消后继。 */ Node s = node.next; if (s == null || s.waitStatus > 0) { s = null; for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } if (s != null) LockSupport.unpark(s.thread); }
/** * Fair version of tryAcquire. Don't grant access unless * recursive call or no waiters or is first. */ protectedfinalbooleantryAcquire(int acquires){ final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); returntrue; } } elseif (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) thrownew Error("Maximum lock count exceeded"); setState(nextc); returntrue; } returnfalse; }
/** * Queries whether any threads have been waiting to acquire longer * than the current thread. * 查询是否有任何线程在等待获取比当前线程更长的时间。 * * <p>An invocation of this method is equivalent to (but may be * more efficient than): * <pre> {@code * getFirstQueuedThread() != Thread.currentThread() && * hasQueuedThreads()}</pre> * 对此方法的调用等效于(但可能比它更有效): * <pre> {@code getFirstQueuedThread()!= Thread.currentThread()&& hasQueuedThreads()} <pre> * * <p>Note that because cancellations due to interrupts and * timeouts may occur at any time, a {@code true} return does not * guarantee that some other thread will acquire before the current * thread. Likewise, it is possible for another thread to win a * race to enqueue after this method has returned {@code false}, * due to the queue being empty. * 请注意,由于中断和超时引起的取消可能随时发生, * 因此{@code true}返回值不能保证某些其他线程将在当前线程之前获取。 * 同样,由于队列为空,因此此方法返回{@code false}后,另一个线程也有可能赢得竞争。 * * <p>This method is designed to be used by a fair synchronizer to * avoid <a href="AbstractQueuedSynchronizer#barging">barging</a>. * Such a synchronizer's {@link #tryAcquire} method should return * {@code false}, and its {@link #tryAcquireShared} method should * return a negative value, if this method returns {@code true} * (unless this is a reentrant acquire). For example, the {@code * tryAcquire} method for a fair, reentrant, exclusive mode * synchronizer might look like this: * 方法设计为由公平同步器使用,以避免<a href="AbstractQueuedSynchronizerbarging">插入<a>。 * 此类同步器的{@link tryAcquire}方法应返回{@code false},并且如果此方法返回{@code true}(除非这是可重入获取),则其{@link tryAcquireShared}方法应返回负值。 * 例如,用于公平,可重入,互斥模式同步器的{@code tryAcquire}方法可能如下所示: * * <pre> {@code * protected boolean tryAcquire(int arg) { * if (isHeldExclusively()) { * // A reentrant acquire; increment hold count * return true; * } else if (hasQueuedPredecessors()) { * return false; * } else { * // try to acquire normally * } * }}</pre> * * @return {@code true} if there is a queued thread preceding the * current thread, and {@code false} if the current thread * is at the head of the queue or the queue is empty * @since 1.7 */ publicfinalbooleanhasQueuedPredecessors(){ // The correctness of this depends on head being initialized // 正确性取决于 head 被初始化 // before tail and on head.next being accurate if the current // thread is first in queue. // 如果当前线程是第一个入队,则在tail和head.next之前是准确的。 Node t = tail; // Read fields in reverse initialization order // 以相反的初始化顺序读取字段 Node h = head; Node s; return h != t && ((s = h.next) == null || s.thread != Thread.currentThread()); }