Java 并发包 AQS 实现 中 acquireQueued 源码理解的问题

2020-09-04 19:14:19 +08:00
 SachinBeyond

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); } }

我们知道 AQS 有一个等待队列存放 因获取不到锁而阻塞的线程节点。
从上面的 实现中我们也看到  当锁被释放的时候  唤醒下一个节点线程的规则是  获取 head 节点的 next 节点作为下一个要被唤醒的节点,然后让这个节点尝试获取锁,也就是    if (p == head && tryAcquire(arg))  。 判断当前节点的前屈是否是 head,如果是就尝试获取锁。当 if 执行成功的时候就会退出 for 循环

问题: ( 1 ) for 死循环仅有一种退出方式(上面提到的  )吗?
 ( 2 )我们不是说 ReentrantLock 等待可中断吗? 但是从 for 死循环中 我们看到即使你 中断了 也退出不 for 循环吧?
588 次点击
所在节点    问与答
1 条回复
SachinBeyond
2020-09-04 19:15:16 +08:00
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);
}
}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/704311

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX