JDK8中AQS排队获取锁时被中断为何未取消锁获取?
问题现象原因解答
核心原因:该逻辑属于JDK8 AQS中不可响应中断的锁获取默认实现,是JUC设计时刻意选择的行为
结合你给出的acquireQueued源码可以直接看到逻辑细节:
- 整个方法被无限自旋
for(;;)包裹,正常流程下只有成功获取到锁才会退出循环,不会主动终止锁争抢 - 当线程在挂起状态被中断时:
parkAndCheckInterrupt()方法调用Thread.interrupted()返回中断状态的同时会直接清除线程的中断标记,所以系统层面的中断信号被消费掉了- 代码仅会将局部变量
interrupted标记为true,没有任何跳出循环、触发取消流程的逻辑,下一轮自旋会正常执行 - 如果当前还没到当前节点拿锁的时机,线程会再次进入挂起状态,表现得就像没被中断过
- 中断标记不会被丢弃,只是被暂存了:等线程最终成功拿到锁之后,会把
interrupted的结果返回给上层调用方,上层acquire方法会调用selfInterrupt()重新给线程设置中断标记,交给业务侧自行判断要不要处理中断。
额外说明
如果你需要线程在等待锁的过程中就响应中断、直接取消锁获取,不要用默认的lock()方法,改用lockInterruptibly()方法即可,后者的实现逻辑会在检测到中断时直接抛出InterruptedException,终止锁争抢流程。
内容的提问来源于stack exchange,提问作者A Xuan of programmer
相关产品推荐
相关产品推荐

