/**
* 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
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
// 这里是一个自旋操作,用来进行获取锁或者进入阻塞的动作
for (;;) {
final Node p = node.predecessor();
// 如果前驱节点为头节点(head,其实是一个虚节点,不关联任何线程),
// 并且尝试加锁(tryAcquire)成功的话,讲当前节点设置为头节点(head)
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// 如果当前节点的前驱节点不是头节点,或者是头节点但是没有抢到锁(被非公平锁抢占了)
// 就会通过shouldParkAfterFailedAcquire判断当前节点是否需要将自己挂起,进入阻塞状态
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
/**
* 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.
*
* @param pred node's predecessor holding status
* @param node the node
* @return {@code true} if thread should block
*/
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
// 如果当前节点的前驱节点的waitStatus为Node.SIGNAL的话,
// 就意味着当前节点需要进入阻塞状态,将自己挂起
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
return true;
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
// 如果当前节点的前驱节点的waitStatus>0的话,意味着前驱节点的waitStatus=CANCELLED,
// 那么就要从前往后遍历,将CALCELLED的前驱节点都从链表中摘除
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不是CANCELLED(1),也不是SIGNAL(-1),
// 那就将当前节点的前驱节点的waitStatus设置为SIGNAL(意思就是当前节点需要进入阻塞状态,
// 当然这里只是先将当前节点的前驱节点的waitStatus设置为SIGNAL,
// 下一轮自旋才能将当前节点设置为阻塞状态)
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}