Java面试进阶:什么情况下Java程序会产生死锁?如何定位、修复?

两个或多个线程之间,由于互相持有对方需要的锁,而永久处于阻塞的状态。

定位死锁:

最常见的方式就是利用 jstack 等工具获取线程栈,然后定位互相之间的依赖关系,进而找到死锁。如果是比较明显的死锁,往往 jstack 等就能直接定位:首先,可以使用 jps 或者系统的 ps 命令、任务管理器等工具,确定进程 ID。其次,调用 jstack 获取线程栈,找到处于 BLOCKED 状态的线程

 Java 提供的标准管理 API,ThreadMXBean,其直接就提供了 findDeadlockedThreads​() 方法用于定位。线程进行快照本身是一个相对重量级的操作,还是要慎重选择频度和时机。

类加载过程发生的死锁,尤其是在框架大量使用自定义类加载时,Java 有官方文档进行了详细解释,并针对特定情况提供了相应 JVM 参数和基本原则。

 

如何在编程中尽量预防死锁呢?

1)尽量避免使用多个锁,并且只有需要时才持有锁。

2)如果必须使用多个锁,尽量设计好锁的获取顺序

3)使用带超时的方法,为程序带来更多可控性。类似 Object.wait(…) 或者 CountDownLatch.await(…),都支持所谓的 timed_wait

4)静态代码分析(如 FindBugs)

 

有时候并不是阻塞导致的死锁,只是某个线程进入了死循环,导致其他线程一直等待,这种问题如何诊断呢?

答:可以通过linux下top命令查看cpu使用率较高的java进程,进而用top -Hp ➕pid查看该java进程下cpu使用率较高的线程。再用jstack命令查看线程具体调用情况,排查问题。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值