You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

死锁排查求助:获取ReentrantLock失败,线程dump无法定位原因

分析ReentrantLock死锁问题:线程等待被持有的锁

看起来你已经抓到了死锁场景的关键线索!让我们一步步拆解这个问题:

核心锁持有与等待关系

从你提供的线程转储片段,我们能明确两个关键线程的锁状态:

  • 等待锁的线程qtp1450652220-77(线程ID=77),它正阻塞等待锁实例 java.util.concurrent.locks.ReentrantLock$NonfairSync@1e319fef
  • 持有锁的线程pool-2-thread-2(线程ID=1651),是当前持有这个锁的所有者

你给出的等待线程调用栈片段如下:

sun.misc.Unsafe.park(Native Method) - waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@1e319fef
at java.util.concurrent.locks.LockSupport.park(LockSupport...)

下一步排查方向

要找到死锁根源,我们还需要补充信息并检查几个关键点:

  1. 获取持有锁线程的完整调用栈
    找到pool-2-thread-2(ID=1651)的完整线程转储,看看它持有锁之后正在执行什么逻辑:

    • 是不是卡在了耗时操作(比如慢数据库查询、外部API调用)?
    • 是不是在等待另一个锁?(如果是,那可能形成了交叉锁死循环)
    • 有没有发生未捕获的异常,导致锁没在finally块中释放?
  2. 检查MyClass的锁使用逻辑

    • 确认锁的释放是否在finally块中:ReentrantLock是显式锁,必须手动调用unlock(),如果获取锁后代码抛出异常却没在finally里释放,锁就会一直被持有
    • 检查重入次数是否匹配:ReentrantLock支持重入,每次lock()都对应一次unlock(),如果重入次数和释放次数不一致,锁也无法正常释放
    • 有没有可能锁被持有后,线程进入了无限循环或者休眠状态?
  3. 额外排查小技巧

    • 如果能在调试环境复现,可以通过ReentrantLock.getHoldCount()查看持有锁线程的锁持有次数,确认是否存在重入次数不匹配的问题
    • 检查是否有多个锁的嵌套使用场景,比如线程A持有锁1等锁2,线程B持有锁2等锁1,这种交叉持有是死锁的常见原因

内容的提问来源于stack exchange,提问作者Dan Gravell

火山引擎 最新活动