ReentrantLock源码解析3--优先响应中断的lockInterruptibly
1.BIO、NIO、AIO的区别2.Controller是线程安全吗3.为什么多线程下会有线程安全问题4.volatile为什么没有原子性?5.JVM的四种内存屏障6.synchronized关键字原理7.synchronized 锁升级 锁降级8.自旋锁、阻塞锁、可重入锁使用解析9.线程间实现通信的几种方式10.ThreadPoolExecutor线程池参数设置技巧11.关于线程同步(7种同步方式)12.ThreadLocal可能引起的内存泄露13.乐观锁的一种实现方式——CAS14.AtomicInteger源码解析15.ReentrantLock源码解析1--获得非公平锁与公平锁lock()16.ReentrantLock源码解析2--释放锁unlock()
17.ReentrantLock源码解析3--优先响应中断的lockInterruptibly
18.ReentrantLock总结19.ArrayBlockingQueue源码解析20.LinkedBlockingQueue源码解析21.Timer / TimerTask 源码解析22.Delay延迟队列- ReentrantLock.lockInterruptibly允许在等待时由其它线程调用等待线程的Thread.interrupt方法来中断等待线程的等待而直接返回,这时不用获取锁,而会抛出一个InterruptedException。
- ReentrantLock.lock方法不允许Thread.interrupt中断,即使检测到Thread.isInterrupted,一样会继续尝试获取锁,失败则继续休眠。只是在最后获取锁成功后再把当前线程置为interrupted状态。
具体实现如下:
1.lock
Lock在第一次获取锁失败后会走:

public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) //中断当前线程 selfInterrupt(); }
addWaiter封装Node节点插入到队列尾部,acquireQueued负责队列的挂起、出队、是否中断

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; } //shouldParkAfterFailedAcquire:判断线程可否安全挂起 //parkAndCheckInterrupt:挂起线程并返回当时中断标识Thread.interrupted() if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) //当parkAndCheckInterrupt返回中断标识为true时修改interrupted interrupted = true; } } finally { if (failed) cancelAcquire(node); } }
2. lockInterruptibly
lockInterruptibly会直接走下面程序

public final void acquireInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (!tryAcquire(arg)) //没有得到独占锁后 doAcquireInterruptibly(arg); }
doAcquireInterruptibly

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 GC failed = false; //这里没有中断标识 //lock和lockInterruptibly区别就是对中断的处理方式 return; } //shouldParkAfterFailedAcquire:判断线程可否安全挂起 //parkAndCheckInterrupt:挂起线程并返回当时中断标识Thread.interrupted() if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) //当parkAndCheckInterrupt返回中断标识为true时立即抛出异常中断线程 throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了