IT评测·应用市场-qidao123.com
标题:
死锁的产生以及如何避免
[打印本页]
作者:
卖不甜枣
时间:
2025-3-11 04:55
标题:
死锁的产生以及如何避免
一、死锁的产生原因
死锁是多个线程(或进程)因竞争资源而陷入无限等待的状态,需同时满足以下
四个须要条件
:
互斥条件(Mutual Exclusion)
资源一次只能被一个线程独占使用(如锁、文件句柄)。
请求与保持(Hold and Wait)
线程在持有至少一个资源的同时,请求其他线程占有的资源。
不可剥夺(No Preemption)
资源只能由持有者主动释放,不能被强制抢占。
循环等待(Circular Wait)
多个线程形成环形等待链,每个线程都在等待下一个线程释放资源。
二、典型死锁场景示例
Java 代码示例
:
public class DeadlockDemo {
private static final Object lockA = new Object();
private static final Object lockB = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (lockA) {
System.out.println("Thread1 holds lockA");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lockB) { // 等待Thread2释放lockB
System.out.println("Thread1 holds lockB");
}
}
}).start();
new Thread(() -> {
synchronized (lockB) {
System.out.println("Thread2 holds lockB");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lockA) { // 等待Thread1释放lockA
System.out.println("Thread2 holds lockA");
}
}
}).start();
}
}
复制代码
结果
:
两个线程互相等待对方释放锁,程序无限卡死。
三、死锁的检测与诊断
1. 使用工具检测死锁
jstack
(Java自带工具):
jstack <pid> # 输出线程快照,显示死锁的线程及持有/等待的锁
复制代码
VisualVM
或
JConsole
:
图形化界面查看线程状态,直接标记死锁。
2. 日记分析
若日记中线程长时间处于 BLOCKED 状态且无进展,大概发存亡锁。
四、死锁的避免战略
1. 破坏“请求与保持”条件
一次性申请全部资源
:
线程在开始执行前申请全部所需资源,否则不执行。
缺点
:资源利用率低,大概导致饥饿。
2. 破坏“不可剥夺”条件
答应抢占资源
:
若线程请求资源失败,强制释放已持有的资源(需支持回滚操纵)。
缺点
:实现复杂,适用于特定场景(如数据库事务)。
3. 破坏“循环等待”条件
资源有序分配法
:
为全部资源类型定义全局次序,线程按次序申请资源。
示例
:
规定必须先申请 lockA 再申请 lockB,避免交叉申请。
// 修改后代码:两个线程均按 lockA → lockB 顺序申请
new Thread(() -> {
synchronized (lockA) {
synchronized (lockB) { /* 逻辑 */ }
}
}).start();
new Thread(() -> {
synchronized (lockA) {
synchronized (lockB) { /* 逻辑 */ }
}
}).start();
复制代码
4. 使用超时机制
实验获取锁时设置超时
:
若在指定时间内未获得锁,放弃并释放已持有的资源,避免无限等待。
Java实现
(使用 ReentrantLock):
Lock lockA = new ReentrantLock();
Lock lockB = new ReentrantLock();
if (lockA.tryLock(1, TimeUnit.SECONDS)) {
try {
if (lockB.tryLock(1, TimeUnit.SECONDS)) {
try { /* 逻辑 */ }
finally { lockB.unlock(); }
}
} finally { lockA.unlock(); }
}
复制代码
5. 镌汰锁的粒度
缩小同步范围
:
仅对须要代码加锁,镌汰锁的持有时间。
使用线程安全的数据结构
:
如 ConcurrentHashMap 替代 synchronized + HashMap。
五、最佳实践总结
战略
适用场景
长处
缺点
资源有序分配多锁交叉申请场景简朴有用,预防循环等待需全局统一次序,大概限制灵活性超时机制高并发、答应重试的场景避免无限等待,提升体系结实性需处理超时重试逻辑无锁编程(CAS、原子类)低竞争、简朴操纵场景高性能,无死锁风险复杂逻辑实现困难事务回滚数据库、支持回滚的操纵保证数据同等性实现资本高
六、总结
死锁的避免需联合业务场景选择符合的战略:
关键体系
(如金融交易):优先使用资源有序分配和超时机制。
高并发体系
:镌汰锁粒度,采用无锁数据结构。
复杂事务
:联合事务管理和回滚机制。
通过代码规范、工具检测和设计优化,可显著降低死锁发生概率。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/)
Powered by Discuz! X3.4