ReentrantLock加锁流程之lockInterruptibly方法
lockInterruptibly方法的流程是:线程放入AQS链表中,如果前一个节点不是head节点,则挂起;如果是,则尝试获取锁资源。线程被挂起后,在两种情况下会被唤醒,第一种是正常被唤醒,此时可以拿到锁资源;第二种是被中断唤醒,此时抛出中断异常。
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
public final void acquireInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
}
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
// 线程放入AQS链表中
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
// 如果前一个节点是head节点,则尝试获取锁资源
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return;
}
// 线程被挂起,但是被中断会唤醒,抛出中断异常
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}