Arthas实战-排查死锁
一、 准备测试应用
- 新建一个测试程序,写一段线程死锁的代码:
1 | import java.util.*; |
二、使用Arthas排查问题
- 启动 Arthas:
java -jar arthas-boot.jar
- 查看总体使用情况:
dashboard
可以看到已经有死锁线程了 - 查看总体线程使用情况:
thread
BLOCKED线程数量:2,并且显示了具体的BLOCKED线程
- 定位死锁的位置:
thread -b
输出解释:
- 线程信息:
Thread 2
的ID为22,当前状态为BLOCKED
。这意味着它正在等待获取某个对象锁。 - 阻塞原因:
Thread 2
被阻塞是因为需要获取的对象java.util.ArrayLIst@1d0be4d0
正被另一个线程所持有。 - 锁持有者:该对象锁
java.util.ArrayLIst@1d0be4d0
目前被Thread 1
(ID为21)持有。 Thread 1
的状态:虽然输出信息没有直接展示Thread 1
的状态,但从上下文可以推断,Thread 1
locak了java.util.ArrayLIst@1d0be4d0
。Thread 2
lock了java.util.ArrayLIst@1f2efe1c
- 相互阻塞:最关键的信息是
ownd by'thread 1
,指出Thread 2
尝试获取的锁被Thread 1
持有,同时说明Thread 1
至少在某一点上也尝试获取Thread 2
持有的锁(或者导致了其他形式的循环等待),从而形成了死锁。这里的but blocks 1 other threads!
暗示了这种相互阻塞的关系。
到目前为止。基本已经定位到死锁的具体原因和位置了。
- 查看死锁线程详细信息:
thread 21
thread 22
根据上面的信息,我们可以清晰地看到两个线程Thread 1
和Thread 2
都处于阻塞状态,形成了死锁:
Thread 1 (Id=21)
的状态也是BLOCKED
,它在Test.java:38行尝试获取对象java.util.ArrayLIst@1f2efe1c
的锁,而这个锁正被Thread 2
持有。Thread 2 (Id=22)
的状态是BLOCKED
,它在Test.java:23行尝试获取对象java.util.ArrayLIst@1d0be4d0
的锁,但这个锁正被Thread 1
持有。
这种相互等待对方释放锁的情形正是死锁的经典表现。每个线程都持有一个锁,并尝试获取对方的锁,导致双方都无法继续执行下去。
Thread 1
在执行到Test.java的第38行时阻塞,等待java.util.ArrayLIst@1f2efe1c
的锁。Thread 2
在执行到同文件的第23行时阻塞,等待java.util.ArrayLIst@1d0be4d0
的锁。- 两个线程互相等待对方释放锁,形成了死锁。
解决这个问题的关键在于打破死锁的四大条件之一。即:
- 资源不可重用
- 循环等待
- 资源不可被抢夺
- 吃着碗里的看着锅里的
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 xyhao的博客!