阿里面试官必问:死锁四大必要条件!如何排查、如何避免?90%Java开发答不全!
前言
Java并发面试超级高频压轴题:线程死锁!
几乎所有后端一面必问:
死锁产生的四个必要条件是什么?怎么排查线上死锁?项目中如何彻底避免死锁?
很多人只会背四个条件,但是不会排查、不会规避、说不出落地方案,直接错失满分。
本文一次性讲透:死锁四大必要条件、产生原理、线上排查手段、企业级规避方案,面试直接绝杀!
一、什么是死锁
死锁:
两个或多个线程互相持有对方需要的锁,同时等待对方释放锁,谁都不释放、谁都不前进,程序永久阻塞,CPU 正常、业务卡死。
死锁一旦发生,只能重启服务解决,危害极大。
二、死锁四大必要条件(面试必背,缺一不可)
重点:四个条件必须同时满足,才会产生死锁!
1. 互斥条件
资源是独占的,一个线程持有锁,其他线程无法获取。
(synchronized、ReentrantLock 都是互斥锁)
2. 请求与保持条件
线程已经持有一把锁,在不释放的情况下,继续请求另一把锁。
3. 不可剥夺条件
锁只能自己主动释放,别人不能强行抢占。
4. 循环等待条件
线程之间形成闭环等待:
线程A 等 线程B 的锁
线程B 等 线程A 的锁
形成闭环依赖。
三、核心原理(面试加分)
只要破坏任意一个条件,死锁就无法发生!
这是我们避免死锁的理论依据。
四、如何排查线上死锁?(实战+面试必问)
1. jstack 命令排查(最常用)
jstack -l 进程ID
搜索关键字:Found one Java-level deadlock
直接打印:
- 死锁线程名
- 死锁锁对象
- 卡死代码行数
2. 借助 JDK 自带工具
- Jconsole、JvisualVM 可视化查看死锁线程
3. 线上特征
- 接口超时、请求堆积
- 线程状态大量 BLOCKED
- CPU 不高、业务完全不动
五、如何避免/解决死锁?(企业实战方案)
对应四大条件,针对性破坏:
1. 破坏「循环等待」(最常用、最有效)
统一锁获取顺序
所有线程必须按照固定顺序获取多把锁。
比如:永远先锁A、再锁B,绝不颠倒,彻底杜绝闭环等待。
2. 破坏「请求与保持」
加锁前一次性申请所有需要的锁,不持有锁再去申请新锁。
3. 破坏「不可剥夺」
使用 ReentrantLock 的 tryLock() 超时获取锁
拿不到锁就主动放弃、释放已有锁,避免死等。
4. 缩小锁范围
尽量减少锁持有时间,代码块加锁,不要方法加锁。
5. 避免嵌套锁
业务开发禁止多层锁嵌套,90%死锁都是嵌套锁导致。
六、面试满分标准回答(直接背诵)
死锁产生必须同时满足四大必要条件:互斥条件、请求与保持条件、不可剥夺条件、循环等待条件。
排查死锁可以使用 jstack 命令查看线程堆栈,搜索 deadlock 定位卡死线程和代码位置。
避免死锁核心是破坏任意一个必要条件,项目中最常用方案:
统一锁的获取顺序、使用 tryLock 超时机制、缩小锁粒度、杜绝锁嵌套、一次性申请所有锁。
七、高频面试误区
❌ 误区1:四个条件满足三个就会死锁
错!必须四个同时满足才会死锁。
❌ 误区2:死锁是CPU飙升
错!死锁线程是 BLOCKED,CPU 很低,业务卡死。
❌ 误区3:synchronized 可以主动抢占锁
错!synchronized 不可剥夺,只能等对方释放。
总结
死锁面试核心就三点:
吃透这道题,并发基础面试直接稳过!
网硕互联帮助中心



评论前必须登录!
注册