导读:本期聚焦于小伙伴创作的《如何解读jstack导出的线程Dump文件 BLOCKED与WAITING状态的死锁排查》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何解读jstack导出的线程Dump文件 BLOCKED与WAITING状态的死锁排查》有用,将其分享出去将是对创作者最好的鼓励。

在Java应用运行过程中,线程阻塞、死锁等问题会直接导致服务响应变慢甚至不可用,jstack是JDK自带的线程堆栈分析工具,导出的线程Dump文件能够完整记录当前JVM中所有线程的运行状态、持有锁和等待锁的信息,是排查这类问题的核心依据。其中BLOCKED和WAITING是两种常见的阻塞状态,很多开发者容易混淆两者的区别,也不清楚如何从Dump文件中定位死锁根源。

如何解读jstack导出的线程Dump文件 BLOCKED与WAITING状态的死锁排查

线程Dump文件基础结构

执行jstack -l 进程ID命令即可导出线程Dump文件,文件内容按线程为单位分段展示,每个线程段包含以下核心信息:

  • 线程名称、优先级、线程ID、本地ID
  • 线程当前状态,比如BLOCKED、WAITING、RUNNABLE等
  • 线程调用堆栈,展示方法调用的层级关系
  • 锁相关信息,包括持有的锁、等待的锁、锁的地址和所属类

以下是一个简化的线程Dump片段示例:

"thread-1" prio=5 tid=0x000000001d8b9000 nid=0x2d34 waiting for monitor entry [0x000000001f7ff000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at com.example.DeadLockService.methodA(DeadLockService.java:20)
	- waiting to lock <0x00000000d5c8a2b8> (a java.lang.Object)
	- locked <0x00000000d5c8a2c8> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:748)

BLOCKED与WAITING状态的区别

BLOCKED状态

线程处于BLOCKED状态时,是在等待进入synchronized修饰的同步代码块或方法,因为对应的对象锁已经被其他线程持有,所以当前线程被阻塞。BLOCKED状态的线程不会自动唤醒,只有持有锁的线程释放锁之后,才会参与锁的竞争。

在Dump文件中,BLOCKED状态的线程会明确标注waiting for monitor entry,同时会列出waiting to lock的锁对象信息。

WAITING状态

线程处于WAITING状态时,是调用了Object.wait()Thread.join()LockSupport.park()等方法,主动放弃了CPU执行权,等待其他线程的唤醒。WAITING状态的线程不会占用CPU资源,直到其他线程调用对应的notify()notifyAll()或者中断该线程,才会重新进入就绪状态。

在Dump文件中,WAITING状态的线程会标注waiting on condition,同时会列出等待的条件或者关联的锁对象。

死锁的形成与特征

死锁是指两个或两个以上的线程互相持有对方需要的锁,并且都在等待对方释放锁,导致所有相关线程都无法继续执行的场景。死锁中的线程通常会处于BLOCKED状态,因为都在等待对方持有的synchronized锁。

死锁的核心特征:

  • 至少两个线程互相持有对方等待的锁
  • 所有死锁线程都处于BLOCKED状态
  • 线程的等待锁和持有锁形成闭环

死锁排查完整步骤

步骤1:导出线程Dump文件

首先通过jps命令获取目标Java进程的ID,然后执行jstack命令导出Dump文件:

# 查看Java进程ID
jps
# 导出线程Dump,保存到文件
jstack -l 12345 > thread_dump.log

步骤2:定位死锁线程

打开Dump文件后,可以直接搜索deadlock关键词,jstack会在文件末尾自动输出检测到的死锁信息,如下所示:

Found one Java-level deadlock:
=============================
"thread-2":
  waiting to lock monitor 0x000000001d8b9c58 (object 0x00000000d5c8a2b8, a java.lang.Object),
  which is held by "thread-1"
"thread-1":
  waiting to lock monitor 0x000000001d8b9d68 (object 0x00000000d5c8a2c8, a java.lang.Object),
  which is held by "thread-2"

Java stack information for the threads listed above:
===================================================
"thread-2":
	at com.example.DeadLockService.methodB(DeadLockService.java:35)
	- waiting to lock <0x00000000d5c8a2b8> (a java.lang.Object)
	- locked <0x00000000d5c8a2c8> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:748)
"thread-1":
	at com.example.DeadLockService.methodA(DeadLockService.java:20)
	- waiting to lock <0x00000000d5c8a2c8> (a java.lang.Object)
	- locked <0x00000000d5c8a2b8> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

步骤3:分析死锁原因

从上面的死锁信息可以看到,thread-1持有锁0x00000000d5c8a2b8,等待锁0x00000000d5c8a2c8;thread-2持有锁0x00000000d5c8a2c8,等待锁0x00000000d5c8a2b8,两者形成闭环,导致死锁。

结合调用堆栈可以找到对应的业务代码,比如上面的死锁出现在DeadLockServicemethodAmethodB方法中,通常是这两个方法获取锁的顺序不一致导致的。

步骤4:修复死锁问题

解决死锁的核心是统一多个线程获取锁的顺序,比如所有线程都先获取锁A再获取锁B,就可以避免闭环。也可以通过使用超时锁、减少锁的持有范围等方式降低死锁发生的概率。

WAITING状态相关阻塞排查

WAITING状态本身不会形成死锁,但如果调用wait()方法的线程没有被其他线程唤醒,也会导致线程一直阻塞。排查时可以查看WAITING线程的调用堆栈,确认对应的唤醒逻辑是否正常,是否存在唤醒线程提前退出、没有执行notify()的情况。

以下是一个WAITING状态的Dump片段:

"wait-thread" prio=5 tid=0x000000001d8ba000 nid=0x2e10 waiting on condition [0x000000001f8ff000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x00000000d5c8a3d8> (a java.lang.Object)
	at com.example.WaitService.doWait(WaitService.java:15)
	- locked <0x00000000d5c8a3d8> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:748)

这段信息表示该线程在WaitService.doWait方法中调用了Object.wait(),正在等待其他线程唤醒0x00000000d5c8a3d8这个对象锁。

注意事项

  • 线程Dump是某一时刻的快照,如果问题偶发,建议多次导出Dump文件对比分析
  • 除了BLOCKED和WAITING,还有TIMED_WAITING状态,是带超时的等待,排查思路和WAITING类似
  • 如果是使用java.util.concurrent包下的锁(比如ReentrantLock)导致的阻塞,线程状态可能是WAITING或者TIMED_WAITING,锁信息会显示为parking to wait for,排查逻辑和synchronized锁类似

jstack线程Dump死锁排查BLOCKED状态WAITING状态修改时间:2026-07-01 22:18:44

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。