先看之前的代码:
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
之前说过当node获取到锁后会跳出死循环,然后会进入fianlly中,当failed为true时进入cancelAcquire,看代码,除了初始化的时候其实没有地方显式的设为true,所以只有异常情况下会进入。
注:在doAcquireInterruptibly中会显式跑出异常,doAcquireInterruptibly和acquireQueued代码差不多。
再看cancelAcquire代码
private void cancelAcquire(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) //waitStatus>0表示该节点是被取消的节点,则会跳过,理论上来说除了前面的异常,不应该有被取消的节点
node.prev = pred = pred.prev;//将node的前置设为第一个waitStatus<=0(正常等待)的节点
// 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.
//如果当前节点是队尾,则移除掉,将队尾指向之前的pred,也就是第一个正常的节点
if (node == tail && compareAndSetTail(node, pred)) {
//再将pred的next设为null,表示是队尾
compareAndSetNext(pred, predNext, null);
} else {//进入else说明node不是队尾(或者是队尾但是cas队尾失败(其实结果也不是队尾,因为被别的线程抢先了))
// If successor needs signal, try to set pred's next-link
// so it will get one. Otherwise wake it up to propagate.
int ws;
//如果前置节点不是head,且ws==-1(如果不是-1则强制cas成-1)
//这里的cas ws没看懂
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
Node next = node.next;
//将node之后的节点链到pred上
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {//如果是头节点就unpark线程
unparkSuccessor(node);
}
node.next = node; // help GC
}
}
网友评论