ReentrantLock 调试技巧:利用 getQueuedThreads() 与 getHoldCount() 监控锁的持有情况
getQueuedThreads()返回等待锁的线程列表,getHoldCount()返回当前线程重入次数,两者结合可定位死锁、锁泄漏和重入异常。建议通过日志或监控指标轻量化接入,并利用Java19增强线程转储功能辅助调试。
在并发调试的战场上,ReentrantLock 其实是个挺让人头疼的家伙——你没办法像 synchronized 那样,光靠看一眼线程 dump 就能把锁的持有者和等待队列看得清清楚楚。不过别急着挠头,有两个被不少人忽略的实用工具——getQueuedThreads() 和 getHoldCount(),能帮你快速定位死锁、锁泄漏,甚至是那些莫名其妙的重入异常。

先说说这俩工具分别能干什么。
查看当前等待锁的线程列表
getQueuedThreads() 返回一个列表,里面按 FIFO 顺序排着所有已经调用了 lock()、但还没拿到锁的线程(也就是那些被困在 AQS 同步队列里的倒霉蛋)。注意,它不包含因为 Condition.await() 而挂起的线程。怎么用?几个关键点:
- 在临界区的入口处,或者超时获取锁失败之后立刻调用它,你就能确认有没有线程在排队等锁。
- 配合
Thread.getName()和Thread.getState(),可以判断线程是不是卡在了 BLOCKED 状态。 - 但它返回的是个快照,多线程环境下结果可能瞬间就变了,所以最好配合日志或者通过 JMX 暴露成监控指标来使用。
确认当前线程对锁的重入深度
getHoldCount() 是一个实例方法,必须由持有该锁的线程调用才有效——它返回当前线程对该锁的重入次数。如果线程没持有锁,就返回 0。这个值很关键:
- 在嵌套锁逻辑的入口和出口前后打印这个值,就能验证重入次数是否符合预期(比如递归调用、回调等场景)。
- 如果业务逻辑本应是“非重入”的,但这个值大于 1,那就说明存在意外的重复
lock()调用,极可能导致unlock()不匹配。 - 跟
isHeldByCurrentThread()一起用,能构建更健壮的断言,比如assert lock.isHeldByCurrentThread() && lock.getHoldCount() == 1;,双重确认,心里踏实。
组合使用定位典型问题
单看一个方法信息有限,把两者结合起来分析才能揭示真实状况:
- 死锁? 如果某个线程在
getQueuedThreads()中持续出现,并且它的堆栈显示正在等待另一个 ReentrantLock,那就同时检查一下它自己持有的锁(通过getHoldCount()> 0 判断)是否也被别人排队等着。双管齐下,死锁几乎无所遁形。 - 锁泄漏? 服务运行一段时间后,如果发现
getQueuedThreads().size()持续增长,但活跃线程数保持稳定——多半是有lock()之后忘了unlock(),尤其是在异常分支里。 - 误用可重入性? 日志里发现某个线程的
getHoldCount()达到 5 次以上,而且没有明显的递归逻辑——那就赶紧检查一下,是不是在循环或者监听器里反复调用lock()了。
实际调试建议
别等到线上出故障了才临时抱佛脚去加日志。这里更推荐一种轻量化的接入方式:
- 把
lock.getQueueLength()(它返回等待线程数量,比getQueuedThreads()开销小)作为 Micrometer 指标,定时上报,随时掌握全局排队情况。 - 在统一的锁模板方法(比如
withLock(Runnable))里,打开 debug 日志时自动记录getHoldCount()和排队长度。这样既不会影响生产性能,排查时又能拿到一手信息。 - 如果用的是 Ja va 19 或更高版本,JVM 启动时加上
-Djdk.locks.friendly=true,可以增强 jstack 对 ReentrantLock 的识别能力,让线程 dump 里出现“waiting for lock”这样更清晰易懂的提示。
Postman是一套面向API全生命周期的开发与测试平台,可在Mac上发送和调试多种协议请求,管理集合、环境及认证信息,并完成脚本测试、模拟服务、监控、文档发布和团队协作。它适合开发、测试及运维人员使用,提供个人免费方案。
Docker Desktop 是 Docker 官方为 Mac 提供的容器开发环境,集成 Docker Engine、命令行工具、Compose、Build、Kubernetes 与图形化管理界面。
Android Studio 是 Google 面向安卓应用开发提供的官方集成开发环境,基于 IntelliJ IDEA 构建。它整合智能代码编辑、Gradle 构建、界面预览、设备模拟、性能分析、调试测试及 APK 分析等工具。
Postman 是面向 API 全生命周期的开发与协作平台。Windows 桌面版可用于构建和发送 HTTP、GraphQL、gRPC、WebSocket、MQTT 等请求,并提供环境变量、集合、脚本测试、模拟服务、监控、文档及团队工作区等
Docker Desktop 为 Windows 开发者提供集成式容器环境,内置 Docker Engine、命令行工具、Compose、Build 与 Kubernetes 等组件,可在本机完成镜像构建、容器运行、日志查看和资源管理。
Android Studio 是 Google 面向 Android 应用开发提供的官方集成开发环境,以 IntelliJ IDEA 为基础,集成智能代码编辑、Gradle 构建、设备模拟、界面预览、调试测试及性能分析工具,













