finalbooleanacquireQueued(final Node node, int arg) { booleanfailed=true; try { booleaninterrupted=false; // 当前线程释放中断的标志位 for (;;) {// 不断尝试 finalNodep= node.predecessor(); // 获取前一个节点 if (p == head && tryAcquire(arg)) { // 如果前一个节点是head,尝试抢一次锁 setHead(node); // 更换head p.next = null; // help GC failed = false; return interrupted; } // 检查在当前节点之前的线程节点状态,是否需要挂起线程 if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())// 如果需要挂起,则通过Park进入停车场挂起 interrupted = true; // 如果出现中断,则修改标记 } } finally { if (failed) cancelAcquire(node); } }
final Node predecessor()throws NullPointerException { // 当前节点前如果没有其它节点,那就肯定是head节点 Nodep= prev; if (p == null) thrownewNullPointerException(); else return p; }
privatestaticbooleanshouldParkAfterFailedAcquire(Node pred, Node node) { intws= 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) { // 前置节点处于CANCELLED状态,跳过它继续寻找正常的节点,并且甩掉中间那段不正常的节点 /* * 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. */ compareAndSetWaitStatus(pred, ws, Node.SIGNAL); // 修改前置的状态为SIGNAL,用意是释放锁之后会通知后续节点 } returnfalse; }
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. */ 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. */ Nodes= node.next; // 找下一个节点 if (s == null || s.waitStatus > 0) { // 如果不存在或者被取消了,继续寻找合适的下一个节点 s = null; for (Nodet= tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } if (s != null) // 如果找到了合适的节点,就唤醒它 LockSupport.unpark(s.thread); }