AQS打断原理

阅读: 评论:0

AQS打断原理

AQS打断原理

不可打断模式

平时加锁使用的 reentrantLock.lock() 方法, 默认是不可打断模式,即便 park 状态的线程被打断了,它也不会立即响应,它仍旧在 AQS 中运行着,直到拿到锁,再自己中断自己。

private final boolean parkAndCheckInterrupt() {LockSupport.park(this); // 线程停在了这里。// 获取当前线程是否被打断了,并且清空打断标记。return Thread.interrupted();
}

假设 T1 处于 park 状态,但被 T2 拿到了 T1的线程对象,调用 t1.interrupt() 方法,将 t1 从打断中给唤醒了。parkAndCheckInterrupt() 返回 true。

final boolean acquireQueued(final Node node, int arg) {// 拿锁失败?默认是。boolean failed = true;try {boolean interrupted = false;for (;;) // 如果获得不了锁,T1 依旧会进入 park。final Node p = node.predecessor();if (p == head && tryAcquire(arg)) {setHead(node);  p.next = null; failed = false;// T1 只有拿到锁时,才能跳出这个死循环。// 返回 打断标记,true。return interrupted;}if (shouldParkAfterFailedAcquire(p, node) &&            parkAndCheckInterrupt())// 被打断的 T1 执行到这里。interrupted = true;// 死循环,回到上面去重新执行。}} finally {if (failed)cancelAcquire(node);}
}

如果 T1 被打断后,拿到了锁,它返回到哪里了呢

public final void acquire(int arg) {if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // acquireQueued() 返回结果true。// 执行这个方法。selfInterrupt();
}static void selfInterrupt() {// T1自己重新产生一次中断。Thread.currentThread().interrupt();
}

可打断模式

调用 reentrantLock.lockInterruptibly() 那就是可打断的。

public void lockInterruptibly() throws InterruptedException {// 调用 AQS 的 acquireInterruptibly(1) 方法。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 {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 GCfailed = false;return;}if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())// park 的线程被打断后,直接抛异常。throw new InterruptedException();}} finally {if (failed)cancelAcquire(node);}
}

总结

  • reentrantLock.lock() 加锁,线程是不可被打断的,因为即便 T1被打断了,它拿不到锁,从循环里出不来,依旧又会 park。
  • reentrantLock.lockInterruptibly() 加锁,线程是能可被打断的,park 的线程一旦被打断,直接抛异常。

本文发布于:2024-01-27 21:16:33,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/17063613952687.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:Charles打断点
下一篇:fiddler打断点
标签:原理   AQS
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23