Java死锁
Java死锁
1. 什么是死锁
- 死锁,简单来说就是多个线程被同时阻塞,且每个线程都在等待其他线程释放资源,从而导致所有线程都无法继续执行的状态。
- 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方的资源,所以这两个线程就会互相等待而进入死锁状态。

2. 死锁的产生条件
- 死锁产生的四个必要条件:
- 互斥条件:资源不能被多个线程共享,某个资源一次只能被一个线程占用。
- 请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放。
- 不可剥夺条件:线程已获得的资源在未使用完之前,不能被强制剥夺,只能在使用完后由线程自己释放。
- 循环等待条件:存在一种资源循环等待关系。
3. 如何检测死锁
- 使用
jmap、jstack等命令查看JVM线程栈和堆内存的情况。如果有死锁,jstack的输出中通常会有Found one Java-level deadlock:的字样,后面会跟着死锁相关的线程信息。另外,实际项目中还可以搭配使用top、df、free等命令查看操作系统的基本情况,出现死锁可能会导致CPU、内存等资源消耗过高。 - 采用VisualVM、JConsole等工具进行排查。
4. 如何预防和避免死锁
- 预防死锁,破坏死锁产生的必要条件即可:
- 破坏请求与保持条件:一次性申请所有的资源
- 破坏不可剥夺条件:当线程请求资源时,如果资源不可用,则释放它已获得的资源,稍后再试
- 破坏循环等待条件:靠按序申请资源来避免。按某一顺序申请资源,释放资源则反序释放
- 避免死锁:在资源分配时借助算法对资源分配进行计算评估,如银行家算法
