Skip to content

入门:死锁定义、四条件与饥饿/活锁

基于通用操作系统概念 · 核于 2026-08

速查

  • 死锁定义:一组进程互相等待对方释放资源,每个进程都被阻塞、谁也无法前进的永久僵局——经典场景是两个进程各持一把锁、又去抢对方的锁,结果双双卡死。
  • 本质:资源竞争 + 请求顺序不当。死锁不是 bug(逻辑没错),而是资源管理策略出了问题。
  • 四必要条件(Coffman):①互斥(资源一次只能给一个进程用);②占有并等待(拿着资源不放,同时申请新资源);③不剥夺(资源不能被强行抢走,只能持有者主动释放);④循环等待(存在进程间的环形等待链)。四个全满足才会死锁,破坏任一即预防。
  • 死锁 vs 饥饿:死锁是永久阻塞、卡死不动(等一个永远不会来的事件);饥饿是还能调度、只是轮不到资源(如低优先级进程总被抢占,长期得不到 CPU)。死锁一定伴随饥饿,饥饿不一定是死锁。
  • 死锁 vs 活锁:活锁(livelock)是进程没有阻塞、还在运行,但因互相让步而都无法前进——两人走廊相遇互相让路、结果同步左右换位仍撞上。活锁在动,死锁不动。
  • 资源分配图(RAG):进程与资源的有向图,有环不一定死锁——只有每类资源只有 1 个实例时"有环即死锁";多实例时要化简图(删掉能完成的进程)后看是否还有环。
  • 四种处理策略:预防(破坏四条件)、避免(银行家算法)、检测与恢复(允许发生再处理)、鸵鸟(忽略,Linux/Windows 实际做法)。
  • 进阶顺序死锁四条件与资源分配图死锁处理:预防、避免、检测参考

一、死锁是什么:永久阻塞的僵局

死锁(Deadlock)的经典定义:在一组进程中,每个进程都无限期等待只能由同组另一进程释放的事件(通常是资源)。结果是这组进程全部卡死,谁也走不到下一步。

最经典的例子是"两把锁":

线程 A:                    线程 B:
  lock(lock1);                lock(lock2);
  // 持有 lock1                // 持有 lock2
  lock(lock2);  ← 卡死在这     lock(lock1);  ← 卡死在这
  // 等 B 释放 lock2            // 等 A 释放 lock1
  • A 持有 lock1 等 lock2,B 持有 lock2 等 lock1——两人互相等对方手里的锁,谁也不松手,死锁。
  • 特征:程序卡死不动、CPU 占用通常很低(都在 sleep/等待)、不报错、不崩溃,但业务彻底停滞。

死锁与一般"卡顿"的区别:死锁是永久的,不会因多等一会而自行解开(除非有外部干预——杀进程、超时)。

二、四必要条件:缺一不可

Coffman(1971)指出死锁发生必须同时满足四个条件,称为四必要条件

  1. 互斥(Mutual Exclusion):涉及的资源是排他性的,同一时刻只能被一个进程占用(如打印机、写锁)。若资源可共享(如只读内存),则无需等待,不会死锁。
  2. 占有并等待(Hold and Wait):进程已占有至少一个资源,又在等待获取被其他进程占有的资源——持有不放的同时伸手要新的。
  3. 不剥夺(No Preemption):资源不能被强行夺走,只能由持有者主动释放。若可剥夺(如 CPU 可被调度器抢占),死锁可被打破。
  4. 循环等待(Circular Wait):存在一个进程的等待环 {P0→P1→...→Pn→P0},每个进程都在等下一个进程占有的资源。
  • 为什么是必要条件:四个条件构成死锁的充要组合——任意破坏一个,死锁就不可能发生。这就是预防策略的依据(破坏其一即可)。
  • 为什么"循环等待"最常被破坏:互斥/占有等待/不剥夺是资源的固有属性(打印机天然互斥),难改;而循环等待可以通过"资源有序分配"人为消除。

三、死锁 vs 饥饿 vs 活锁

这三者都是并发系统的病,但机理与表现不同:

死锁(Deadlock)饥饿(Starvation)活锁(Livelock)
状态永久阻塞,完全不动可调度,但长期得不到资源在运行,但无进展
进程是否阻塞是(都在 wait)否(可能就绪/运行)否(在反复让步)
原因互相等待对方的资源调度策略不公(如优先级太低总被抢占)互相响应对方动作,反而都无法前进
经典例子两把锁互等短作业优先(SJF)下长作业永远等不到 CPU走廊相遇互相让路、同步换位仍相撞
是否自行恢复否(需外部干预)可能(调度策略变化后可获资源)可能(随机退避后可解开)
CPU 占用低(都在等)不一定可能高(在空转让步)
  • 死锁一定伴随饥饿(被死锁的进程也"饿"着),但饥饿不一定是死锁(饥饿进程还活着、还能被调度,只是轮不到它)。
  • 活锁比死锁更隐蔽:进程没卡住、监控看线程还"活着",但实际产出为零——分布式系统(如重传冲突)和锁让步(tryLock 失败立即重试)中常见。

下一步

理解了死锁的定义与四条件后,下一步深入死锁的识别工具——死锁四条件与资源分配图(如何用 RAG 判断系统是否死锁),以及四条件如何被破坏以实现预防。