上一篇一起看过了AQS独占锁的获取与释放,这次再一起看一下可中断锁的获取与释放
还是和之前一样直接上代码进行分析
可中断获取锁源码分析
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 {
final Node node = addWaiter(Node.EXCLUSIVE); // 当前线程封装成Node节点追加在链表尾
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) { // 获取同步状态成功
setHead(node);
p.next = null; // help GC
failed = false;
return;
}
if (shouldParkAfterFailedAcquire(p, node) && // 调整前置节点waitStatus状态
parkAndCheckInterrupt()) // 线程中断
throw new InterruptedException(); // 注意此处就是响应中断的来源
}
} finally {
if (failed)
cancelAcquire(node);
}
}
如果看过上篇独占锁的获取源码的话理解这个就非常轻松了,它唯一的区别就是当线程中断之后直接抛出异常,而独占锁的获取当线程中断后是会等待前置节点的唤醒再次进行同步状态的抢占
超时等待获取锁
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquire(arg) ||
doAcquireNanos(arg, nanosTimeout); // 超时等待主要依靠该方法实现
}
private boolean doAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (nanosTimeout <= 0L)
return false;
final long deadline = System.nanoTime() + nanosTimeout; // 计算出等待终止时间
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return true;
}
nanosTimeout = deadline - System.nanoTime(); // 获取同步状态失败后计算剩余时间
if (nanosTimeout <= 0L) // 小于0直接返回false
return false;
if (shouldParkAfterFailedAcquire(p, node) && // 更改前置状态waitStatus的值
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout); // 对当前线程进行阻塞
if (Thread.interrupted()) // 检测当前线程是否被中断
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
这个代码也是很好分析的,可以参照下图进行理解
可中断锁及超时等待获取锁的释放
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
同独占锁的释放