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 循环吧?
1
SachinBeyond OP 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); } } |