请说明在Java程序中死锁产生的典型条件,并给出相应的避免策略。
考察说明
考查对死锁产生机制的理解及实际工程中的预防手段。
回答思路
- 【回答框架 1】死锁是多个线程因竞争共享资源而相互等待,导致无法继续执行的阻塞状态。其产生需同时满足四个必要条件:互斥、持有并等待、不可抢占、循环等待。
- 【回答框架 2】避免死锁的关键在于破坏上述条件之一。常用方法包括:按固定顺序加锁,避免循环等待;使用tryLock设置超时,不满足则释放已持有锁;使用并发容器和锁替代方案如Lock接口、Semaphore等减少锁竞争。
- 【回答框架 3】实际项目中,应减少锁的粒度和持有时间,能不用锁就不用锁。使用无锁数据结构、ThreadLocal或原子变量也可以自然规避。生产环境还应通过jstack等工具诊断死锁,监控死锁检测机制。
- 【回答框架 4】需要注意锁的释放总在finally中,避免异常导致锁未释放。设计时考虑锁顺序的统一约定,并对多资源加锁场景进行评审。
- 【关键点 1】死锁四条件:互斥、持有并等待、不可抢占、循环等待。
- 【关键点 2】避免死锁最常用手段是保证加锁顺序一致。
- 【关键点 3】使用tryLock定时获取锁可降低死锁概率。
- 【关键点 4】减少锁范围和使用无锁结构可有效预防。
- 【易错点 1】仅识别死锁四条件,未给出具体避免方案。
- 【易错点 2】以为synchronized就不会死锁,其实更危险。
- 【易错点 3】忽略锁释放的异常处理,导致死锁隐患。