You need to enable JavaScript to run this app. Java中ReentrantReadWriteLock与synchronized混用死锁问题咨询
优惠活动
大模型
产品
解决方案
定价
更多

Java中ReentrantReadWriteLock与synchronized混用死锁问题咨询

死锁原因与疑问解答

核心死锁逻辑

你的初步猜测存在偏差,结合线程dump给出的阻塞现象,死锁是典型的循环持有等待问题,触发时序如下:

  1. Worker线程执行run方法时,调用static synchronized修饰的Utils.scheduleTask,首先拿到Utils.class类锁,向线程池提交延迟为0的任务。
  2. 由于操作系统调度的不确定性,提交的任务在scheduleTask方法还未执行完成、Worker线程还持有Utils.class锁时,就被schedule线程抢先启动执行。
  3. schedule线程执行任务的过程中,拿到了Worker实例的内置锁(结合你去掉doSomething的synchronized就能解决死锁的现象,你的示例代码中getData方法漏加了synchronized修饰,实际业务代码中该方法应该是同步方法),之后尝试获取ReentrantReadWriteLock的读锁时陷入阻塞。
  4. Worker线程待scheduleTask执行完成、释放Utils.class锁后,执行synchronized修饰的doSomething方法,拿到Worker实例的内置锁,之后调用Utils.getIntValue时,由于实际业务中getIntValue也是static synchronized修饰的,需要获取Utils.class类锁,此时该锁被schedule线程持有,Worker线程陷入阻塞。

两个线程各自持有对方需要的锁,同时等待对方释放锁,形成死锁。去掉doSomething的synchronized修饰后,循环等待的链路被打破,死锁自然消失。

你的疑问解答

1. ReentrantReadWriteLock实例如何感知到引用它的Worker实例已经被其他线程持有内置锁?

完全不会感知。ReentrantReadWriteLock是基于AQS实现的显式锁,和Java对象的内置监视器锁是两套完全独立的锁实现,彼此没有任何关联逻辑,不存在互相感知的机制。

2. 是否在scheduleTask方法执行完成返回后,Utils类的类锁还处于被持有状态,导致提交的定时Runnable运行时还需要等待该锁?

不会。static synchronized方法的锁持有周期和方法执行周期完全一致,方法执行结束返回时,Utils.class的类锁就会被自动释放。后续定时任务运行时不需要等待该锁,除非任务内部也调用了Utils类的静态同步方法。


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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.17 21:54:01