public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
这是 AQS 中的模板 acquire 方法,里面有个 acquireQueued 方法:
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);
}
}
代码逻辑会判断当前节点的前驱结点是不是头结点( p == head ),如果是才去获取锁。我看了下 ReentrantLock 中的非公平锁也会走到这一段逻辑来,那这还叫非公平锁吗? 为什么非公平锁也要去 CLH 队列判断当前线程结点是不是头结点?
1
fatyoung OP 还是说非公平锁只在第一次抢占时才是非公平的? 如果抢占失败进入 CLH 队列,后续跟公平锁一样都是需要判断队列头结点才能继续抢占?
|
2
cweijan 2021-11-11 10:12:15 +08:00 1
非公平锁是调用 lock 的时候立刻执行一次 cas, 如果成功就获取锁, 不获取就走和公平锁一样的逻辑.
|
4
shinyruo2020 2021-11-13 20:28:25 +08:00
仔细看源码就知道了,实际上在一开始,非公平锁会多进行两次 cas ,并不只是一次
|