一、概念
【死锁】就是:
- 【至少2到2个以上】的进程,因为【争抢临界资源】而【循环等待】的情况
- 所有进程都持有别的进程所需要的资源,但是又缺少一部分资源还在别的进程手里
- 所有进程都进入【阻塞态】,没有一个进程在【运行态】
- 比如哲学家例子,所有哲学家都占有相对自己而言的【左筷子】资源,而无法获取【右筷子】资源,要循环等待其他进程释放【左筷子】资源
注意区分【死锁】、【饥饿】、【死循环】
- 【死锁】强调:
- 1、【至少2到2个以上】的进程,而且都在【阻塞态】
- 2、是因为【操作系统这个管理者】对【资源分配策略】不当而导致的现象
- 3、**死锁必然会导致饥饿!!!**而且是永久饥饿
- 【饥饿】强调:
- 1、可能只有1个进程饥饿
- 2、有可能是【阻塞态】(例:得不到I/O资源),也可能是【就绪态】(例:得不到CPU)
- 3、也是因为【操作系统这个管理者】对【资源分配策略】不当而导致的现象
- 4、**饥饿不一定是死锁!!!**只不过是一个进程一直等待而已,终有那么一刻会给他等到资源的
- 【死循环】强调:
- 1、可能是1个进程死循环
- 2、可以是【运行态】,在CPU运行其代码的时候有死循环代码卡住
- 3、是【程序这个被管理者】自身问题,和【操作系统无关】
二、死锁产生的原因、必要条件
【原因】总结就是:各进程争抢需要互斥的临界资源,而操作系统对各个进程获取资源的分配策略不当

【必要条件】:必要!必要!只有4个条件同时发生才会导致死锁!!
缺一不可,只要破坏一个都不会导致死锁了!!!
简单用一个例子解释可以记熟一点:
假设有一个公共厕所,里面有【纸巾】和【坑位】两个资源,有两个进程A和B要用
- 【互斥条件】:同一时刻A和B只能有一个人去蹲坑,总不能两个人同时背靠背用一个坑位拉屎吧?同一时刻A和B也只能一个人去抽纸巾
- 【请求和保持条件】:吃着碗里的想着锅里的!!A先进去占用坑位拉屎了,那B等烦了就也去占了纸巾机;现在A拉完了需要抽纸巾擦屁股,但是B不给A;现在B有了纸巾想拉屎,但是A也占着坑位不给B。
- 【不可抢占条件】:A和B都是文明人,他们只能占着资源但是不能动手!B不可以强行把A光着屁股拖出来,A也不能光着屁股去抢B的纸巾
- 【循环等待条件】:结果就是A要等B的纸巾,B要等A的坑位。可是如果这时候有个第三人C进来带着纸巾,他给了A擦了屁股,A就不用等B了,而A拉完了B也就可以进去用坑位了,就会打破死锁现象。
三、死锁处理

1、不允许死锁发生(静态预防死锁)
【破坏互斥条件】
简单举例:
- 还是刚刚公共厕所的例子,这就相当于发明了一个可以一人蹲一半的坑位,然后A和B可以同时在一个坑位背靠背拉屎了,但是不是所有厕所都可以这样,比如五星级酒店这样就会有伤大雅。。。。
【破坏不剥夺条件】
简单举例:
- 方案一:当A进去坑位一直拉屎不出来,B一直拿着纸巾不拉屎,会有一个厕所管理员去检查,发现B明明又【没有占坑位】,又【占着纸巾】,只有1个资源,那就把它赶出去,把纸巾给A让它擦完屁股
- 方案二:A是普通小市民,B是黑社会大恶霸,B上厕所的优先级更高,B进来了管你A拉没拉完,厕所管理员直接把A赶出去
【破坏请求保持条件】
简单举例:
- 不让你吃着碗里的又想着锅里的,进厕所之前强制让第一个人先拿到【坑位】和【纸巾】2个资源,其他人不许抢!这样A就能顺利拉完然后到B了
缺点:
简单举例:
- 如果还真有这种神人,比如C进来他拉屎不擦屁股,只需要【坑位】这1个资源;D进来不拉屎,只需要【纸巾】擦个嘴;
- 那么如果让A一直占着这2个资源,会造成C和D这么简单的需求都完成不了
- 而如果让像C和D这些进程先执行,一直有这样的进程运行,那A永远不能上坑位拉屎并且擦屁股,A要饿死了
【破坏循环等待条件】
简答举例:
- 还是刚刚那个公共厕所例子:现在给【坑位编号1】、【纸巾编号2】
- 不管是A和B,不管你是想用纸巾还是上厕所,都必须先申请 1 号坑位,再申请 2 号水龙头
- 结果会怎样?
假设A先抢到了 1 号坑位:
- B想申请资源,必须先抢 1 号坑位,但被A占了,只能在外面等
- A占着坑位,再去申请 2 号纸巾(没人抢,直接拿到)
- A用完坑位和纸巾,先释放坑位,再释放水龙头
- B才能拿到坑位,再拿纸巾,顺利完成流程
假设B先抢到了 1 号坑位:
- B只能等A用完,再按顺序申请资源
- 永远不会出现 "一个占着 1 号,一个占着 2 号,互相等" 的情况,这样就直接打破了循环等待条件,死锁根本没法形成!
缺点:这种分配编号顺序在代码层面肯定是麻烦的,每加一个设备都要调编号顺序。而且并不是每个进程都要按编号顺序使用设备,比如B人家压根就不想用坑位,你非要人家蹲一会干拉才能用纸巾。
;
;
【经典例子】
- 情况一:限制拿筷子的哲学家数量,就会留出进程不参与资源竞争,从而打破循环卡死
- 情况二:假设1号拿左筷子,2号拿右筷子时发现被1号拿左筷子时拿走了,于是2号啥也干不了就等待,但2号也没有占用任何资源,因此等价情况一
【计算题重点:什么时候不死锁?什么时候死锁?】
【简洁版总结】
【详细版分析】
字太丑了没办法。。。
;
;
;
;
【例题】
2、不允许死锁发生(动态避免死锁:银行家算法)
1)银行家算法概念
2)【关于计算 "安全序列"】
不管选择题、大题,问题里问【当前情况是否安全?】,意思就是【是否能求出安全序列?】
在计算安全序列之前,名词解释:
- process:是进程
- max:这个进程预估的最多需要几个资源
- allocation:是已分配资源(这个进程已经拿到手了几个资源)
- need:这个进程还需要几个资源,need=max-allocation
- request_i:是该进程Pi本次申请的资源数量,request_i <= need
- 比如上面图片P0进程对3个设备的总共需要是(7,5,3),它已经拿到手(0,1,0),还需要(7,5,3)-(0,1,0)=(7,4,3),然后他此时想申请(2,1,1),不可以申请超过(7,4,3)的资源数
- work=available:这两个单词代表一个意思,就是当前计算机手头还剩几个可用资源
那么计算安全序列的方式,我在网上看到最稳最不容易错的就是,像我下面铅笔这样画表格(甚至可以完全不知道里面的意思,你只用照着模板写就行)以这道题为例子:
- 初始还剩资源是(0,2,1),我们跟4个进程的need对比,发现只满足P1的need(0,0,1)
- 于是写下去表格,后面的计算我就不文字叙述了,最终可以满足P1所有所需资源,P1进程运行结束,【归还自己的进程!!】------> 更新【计算机目前手头还剩资源:(2,2,1)】
- 现在还剩资源是(2,2,1),我们跟除了P1的剩下3个进程的need对比,发现只满足P4的need(2,0,0)
- 于是写下去表格,后面的计算我就不文字叙述了,最终可以满足P4所有所需资源,P4进程运行结束,【归还自己的进程!!】------> 更新【计算机目前手头还剩资源:(2,2,2)】
- 现在还剩资源是(2,2,2),我们跟除了P1、P4的剩下2个进程的need对比,发现没有任何一个进程的需求可以满足!!!
- 于是当前情况找不到任何安全序列!!!不安全,会死锁!!!
3)【判断进程可否给Pi进程分配 "Request_i个资源" 】
这题第二问【T0时刻P3请求1台设备可否】这种问题,需要额外先加2个判断:
- 【Request_i】就是Pi进程此时要请求的资源的数量,【Need_i】是Pi进程还需要几个资源,【Available_i(或者Work_i)】就是整个计算机手头还剩几个资源
- 那【你申请的资源数量】总不能大于【你还需要的资源数】吧?你只需要2台打印机申请5台不就有问题吗?
- 【你申请的资源数量】总不能大于【计算机还剩的可用资源数】吧?计算机就剩2台打印机,你申请5台也申请不了啊?
- 如果以上两个条件都无法满足,那直接拒绝,直接不允许分配就完事了
- 如果上面两个条件都满足,那么再根据新的更新信息,按照第一问的方式计算
;
;
;
【例题】
3、允许死锁发生
1)死锁的检测
【注意:死锁定理】
2)死锁的解除

【资源剥夺法(抢资源给别人用)】
大白话:管理员直接从其中一个死锁进程手里,把资源抢过来,分给另一个进程用,先把活干完。
厕所场景:管理员看AB两人僵住了,直接把 A 从坑位里请出来(挂起进程),把坑位暂时收回来给 B 用
- B 拿到坑位,马上就能上厕所,用完之后,把【坑位】和【纸巾】2个资源都释放出来。
- 然后管理员再把 A 请回坑位,让他继续上厕所,这时候【纸巾】也够了,A 就能顺利擦屁股了。
优缺点:✅ 不用把人赶跑,只是暂时请出去,进程还能继续执行。❌ 万一 A 一直被抢资源,每次都让他让着别人,他可能一直用不上厕所,就 "饿死" 了(进程长时间得不到资源,一直阻塞)
【撤销进程法(直接把进程 "干掉")】
大白话:管理员直接把其中一个死锁进程强制终止,把他手里的所有资源全部收回来,分给别人用。
厕所场景:管理员看劝不动,直接把 A 赶出去(终止进程),不管他上没上完,把坑位直接给 B 用。
- B 拿到坑位,顺利上完厕所,释放所有资源。
- A 只能下次重新排队,从头再来上厕所。
优缺点:✅ 实现超简单,直接解决死锁,不用管复杂的状态。❌ 代价极大!A 已经蹲了 10 分钟,快完事了,被赶出去等于白忙活,所有进度都没了,还要从头再来(进程已经运行很久,终止后需要重新执行,浪费时间)。
【进程回退法(让进程 "时光倒流")】
大白话:管理员让其中一个死锁进程退回到还没拿资源的时候,重新按规则申请资源,避免死锁。
厕所场景:管理员让 A 退回到 "还没进坑位" 的状态(回退到之前的检查点),也就是让他从坑里出来,回到排队的队伍里。
- 现在 A 和 B 都没有拿资源了,管理员规定 "所有人必须【先申请纸巾】,【再申请坑位】"。
- 于是 B 先拿到【纸巾】,再申请【坑位】,顺利完成;
- 然后 A 再按顺序申请,也不会死锁了。
优缺点:✅ 不会浪费进程的进度,只是退回到安全的状态,重新执行就行。❌ 要求很高!系统得一直记录进程的历史状态(比如管理员得记得 A 什么时候进的坑,怎么退回去),实现起来麻烦。
补充:管理员怎么决定 "对谁动手"?
解除死锁时,要选一个 "代价最小" 的进程来处理,对应到厕所场景:
- 进程优先级:如果 B 是领导,A 是普通人,肯定先动 A,不动领导。
- 已执行时间:如果 A 已经蹲了 10 分钟,快完事了;B 刚进来 10 秒,就动 B,别让 A 白忙活。
- 还要多久完成:如果 B 再用 10 秒水龙头就好,A 还要蹲 10 分钟,就动 A,让 B 先用完。
- 已使用资源:如果 A 占着坑位耗了很久,占着资源不撒手,就动他,别浪费资源。
- 交互 / 批处理:如果 B 是急得不行的交互式(比如马上要上班),A 是不着急的(比如没事干),就动 A,保住 B 的紧急需求。



















































【注意:死锁定理】



















