死锁发生的四个必要条件是互斥条件、占有并等待条件、不可剥夺条件和循环等待条件。互斥条件指资源必须独占使用;占有并等待指进程持有资源时又申请新资源且不释放旧资源;不可剥夺指已分配资源不能被强制收回;循环等待指存在进程间环形等待链。

死锁发生必须同时满足四个条件,缺一不可。理解每个条件的含义和对应预防思路,是设计可靠并发系统的基础。
互斥条件:资源不能共享使用
某些资源天然具有排他性,比如打印机、数据库写锁、硬件设备等,同一时刻只能被一个进程独占访问。这个条件通常无法破坏——不是技术做不到,而是语义上不该共享。例如两个事务同时修改同一行数据,必须互斥,否则数据会错乱。
预防重点不在“消除互斥”,而在于:
- 明确区分可共享资源(如只读文件)与必须互斥资源,避免对可共享资源施加不必要的锁
- 缩小互斥范围,比如用行级锁代替表级锁,降低冲突概率
- 减少临界区执行时间,让互斥持有期尽可能短
占有并等待:边占边要,进退两难
一个进程已持有部分资源,又去申请新资源;申请失败时,它既不释放已有资源,也不暂停执行,而是继续等待——这就埋下了死锁伏笔。
常见于多步操作场景,比如事务先更新用户余额,再插入交易日志,中间申请第二个锁失败就卡住。
可行的预防方式包括:
- 静态分配:进程启动前一次性申请全部所需资源,全部满足才运行。简单但易造成资源闲置和饥饿
- 释放再申请:若新资源申请失败,主动释放已占资源,稍后重试。需配合幂等设计,防止重复执行副作用
非抢占条件:资源不能被强行收回
已分配给进程的资源,只能由该进程自行释放,系统不能中途剥夺。这保证了执行一致性,但也让死锁更难打破。
在可控环境下可以适度突破该条件,例如:
- 数据库中对长时间阻塞的事务实施超时回滚,相当于“抢占”其持有的锁
- 操作系统允许终止低优先级进程以回收内存或句柄
- 关键前提是能安全回退——需保存检查点或支持事务回滚,否则强行剥夺会导致数据不一致
循环等待条件:资源请求形成闭环
这是最典型也最容易识别的死锁信号:A等B的资源,B等C的资源,C又等A的资源,构成环形依赖。
根本解法是打破环路,主流做法是资源有序分配:
- 为所有资源编号(如锁ID、表名哈希值、字段顺序等),规定进程必须按升序(或降序)申请
- 这样任意两个进程对资源的请求路径就不会交叉,自然无法成环
- 实际应用中,ORM框架或数据库中间件常内置这类顺序策略,开发者只需保持调用习惯一致
不复杂但容易忽略。










