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) { /* * Predecessor was cancelled. Skip over predecessors and * indicate retry. */ // 说明是个从尾到头的查找过程 do { node.prev = pred = pred.prev; // >0 说明前置节点已经被取消,可以直接删除 } 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. */ // 将前置节点设置为SIGNAL的状态,先入队的线程先被唤醒 compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } returnfalse; }
此处放一个WaitStatus枚举的状态表
1 2 3 4 5 6 7 8 9 10 11
/** waitStatus value to indicate thread has cancelled */ staticfinalint CANCELLED = 1; /** waitStatus value to indicate successor's thread needs unparking */ staticfinalint SIGNAL = -1; /** waitStatus value to indicate thread is waiting on condition */ staticfinalint CONDITION = -2; /** * waitStatus value to indicate the next acquireShared should * unconditionally propagate */ staticfinalint PROPAGATE = -3;
WaitStatus枚举含义
SATUS
当一个Node被初始化的时候的默认值
CANCELLED
为1,表示线程获取锁的请求已经取消了
CONDITION
为-2,表示节点在等待队列中,节点线程等待唤醒
PROPAGATE
为-3,当前线程处在SHARED情况下,该字段才会使用
SIGNAL
为-1,表示线程已经准备好了,就等资源释放了
释放锁的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
publicvoidunlock(){ sync.release(1); }
publicfinalbooleanrelease(int arg){ // 尝试释放锁 if (tryRelease(arg)) { Node h = head; // 如果有等待节点,尝试唤醒(即使创建的临时节点,也会在实际入队的过程中将临时节点改成SIGNAL状态) if (h != null && h.waitStatus != 0) // 唤醒 unparkSuccessor(h); returntrue; } returnfalse; }
tryRelease 释放锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
protectedfinalbooleantryRelease(int releases){ // state - release 重入次数 - 释放次数 int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) // 当前线程不为持有锁的线程 thrownew IllegalMonitorStateException(); boolean free = false; // state = 0,代表释放锁 if (c == 0) { free = true; // 全部释放 setExclusiveOwnerThread(null); } setState(c); return free; }
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. */ int ws = node.waitStatus; if (ws < 0) // 头节点<0,设置为初始状态 (小于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) // 唤醒节点,再走入刚刚的acquireQueued方法 LockSupport.unpark(s.thread); }
privatevoidcancelAcquire(Node node){ // Ignore if node doesn't exist if (node == null) return;
node.thread = null;
// Skip cancelled predecessors Node pred = node.prev; while (pred.waitStatus > 0) // 删除前面取消的节点 node.prev = pred = pred.prev;
// predNext is the apparent node to unsplice. CASes below will // fail if not, in which case, we lost race vs another cancel // or signal, so no further action is necessary. Node predNext = pred.next;
// Can use unconditional write instead of CAS here. // After this atomic step, other Nodes can skip past us. // Before, we are free of interference from other threads. node.waitStatus = Node.CANCELLED;
// If we are the tail, remove ourselves. if (node == tail && compareAndSetTail(node, pred)) { // 尾节点,直接删除当前 compareAndSetNext(pred, predNext, null); } else { // If successor needs signal, try to set pred's next-link // so it will get one. Otherwise wake it up to propagate. int ws; if (pred != head && ((ws = pred.waitStatus) == Node.SIGNAL || (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) && pred.thread != null) { // 找到前一个被唤醒的节点 Node next = node.next; // 如果当前节点的下一个节点是符合被唤醒的条件, // 将前一个符合被唤醒的节点的下一个节点设置为当前节点的下一个节点 if (next != null && next.waitStatus <= 0) compareAndSetNext(pred, predNext, next); } else { unparkSuccessor(node); }
// 尝试获取锁的入队操作 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) { /* * Predecessor was cancelled. Skip over predecessors and * indicate retry. */ do { // 删除cancel的节点(先建立后面指向前面的指针,再建立前面到后面的指针) 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); } 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. */ 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); }