最近我看到了AQS的源代码,现在我有很多问题。
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);
}
}
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
return true;
if (ws > 0) {
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
这些是源代码旋转请求锁定。而且我们意识到队列中的大多数线程将被驻留。
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
在unparkSuccessor中,下一个线程将被唤醒。因此,如果线程第一次无法获取,它将被停放并在队列中等待唤醒。它仍然需要顺序唤醒。我在ReentrantLock中查看了NonfairSync,一旦线程插入队列,它将是FIFO。我认为这只是实施相对不公平。我不知道这是否正确。