You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何给定Java同步方法代码未发生预期死锁?

为什么这段代码没有发生预期的死锁?

嘿,这个问题抓得特别准!你已经观察到了代码里“看似会互相等待”的场景,但实际没触发死锁,核心原因是Java中synchronized修饰的内置锁是可重入锁。

先拆解代码的执行流程

我们一步步理清楚两个线程的行为:

  1. 主线程启动后,调用testClass.func1()——因为func1是synchronized方法,主线程成功获取了TestClass实例的内置锁。
  2. 主线程在func1内部调用func2(),虽然func2也是synchronized方法,但当前线程已经持有这把锁了,所以不需要等待,直接进入func2执行(这就是可重入锁的核心特性)。
  3. 与此同时,ThreadSample线程启动,调用testClass.func2()——它尝试获取TestClass实例的锁,但这把锁已经被主线程牢牢拿着,所以这个线程会进入阻塞等待状态。
  4. 主线程在func2里执行完空循环后,又调用func1()——同样,因为已经持有锁,直接进入递归调用,不会被自己阻塞。

可重入锁的本质

Java的每个内置锁都绑定了两个关键信息:

  • 持有该锁的线程
  • 一个持有计数
    当线程第一次获取锁时,计数设为1;如果同一个线程再次请求这把锁,计数就会加1;每次线程退出synchronized方法/代码块,计数减1,只有当计数回到0时,锁才会被释放,其他线程才有机会获取。

为什么没有死锁?

死锁的形成需要满足四个必要条件:互斥、请求与保持、不剥夺、循环等待。而你的代码里,根本没形成“循环等待”:

  • 主线程自始至终持有锁,一直在递归执行func1→func2→func1的逻辑,它从来没有等待ThreadSample线程持有的任何资源;
  • ThreadSample线程只是单方面等待主线程释放锁,没有反过来让主线程等待它。

说白了,这不是“互相等待”,只是一个线程在等另一个线程释放锁,而持有锁的线程一直在自己递归执行,自然不会触发死锁。

补充:这段代码其实会触发StackOverflowError,因为主线程一直在递归调用func1和func2,栈帧会不断累积直到超出JVM的栈容量,但这和死锁是完全不同的问题哦。

内容的提问来源于stack exchange,提问作者jack.math

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:02:28