@@ -153,6 +153,93 @@ tag:
153
153
154
154
注意,只有四个条件同时成立时,死锁才会出现。
155
155
156
+ ### 2.8 解决死锁的方法
157
+
158
+ #### 那么解决死锁的方法是什么呢?
159
+
160
+ 解决死锁的方法可以从多个角度去分析,一般的情况下,有** 预防,避免,检测和解除四种** 。
161
+
162
+ - ** 预防** 是采用某种策略,** 限制并发进程对资源的请求** ,从而使得死锁的必要条件在系统执行的任何时间上都不满足。
163
+
164
+ - ** 避免** 则是系统在分配资源时,根据资源的使用情况** 提前做出预测** ,从而** 避免死锁的发生**
165
+
166
+ - ** 检测** 是指系统设有** 专门的机构** ,当死锁发生时,该机构能够检测死锁的发生,并精确地确定与死锁有关的进程和资源。
167
+ - ** 解除** 是与检测相配套的一种措施,用于** 将进程从死锁状态下解脱出来** 。
168
+
169
+ #### 死锁的预防
170
+
171
+ 死锁四大必要条件上面都已经列出来了,很显然,` 只要破坏四个必要条件中的任何一个就能够预防死锁的发生 ` 。
172
+
173
+ 破坏第一个条件 ** 互斥条件** :使得资源是可以同时访问的,这是种简单的方法,磁盘就可以用这种方法管理,但是我们要知道,有很多资源** 往往是不能同时访问的** ,所以这种做法在大多数的场合是行不通的。
174
+
175
+ 破坏第三个条件** 非抢占** :也就是说可以采用** 剥夺式** 调度算法,但剥夺调度方法目前一般仅适用于** 主存资源** 和** 处理器资源** 的分配,并不适用于所以的资源,会导致** 资源利用率下降** 。
176
+
177
+ 所以一般比较实用的** 预防死锁的方法** ,是通过考虑破坏第二个条件和第四个条件。
178
+
179
+ - ** 静态分配策略** :所谓静态分配策略,就是指一个进程必须在执行前就申请到** 它所需要的全部资源** ,并且知道它所要的资源都得到满足之后才开始执行。这种做法破坏了死锁产生的第二个条件** 占有并等待** ,进程要么占有所有的资源然后开始执行,要么不占有资源,不会出现占有一些资源等待一些资源的情况。
180
+ 静态分配策略逻辑简单,实现也很容易,但这种策略** 严重地降低了资源利用率** ,因为在每个进程所占有的资源中,有些资源是在比较靠后的执行时间里采用的,甚至有些资源是在** 额外的情况** 下才是用的,这样就可能造成了一个进程占有了一些** 几乎不用的资源而使其他需要该资源的进程产生等待** 的情况。
181
+
182
+ - ** 层次分配策略** :层次分配策略破坏了产生死锁的第四个条件(** 循环等待** )。在层次分配策略下,所有的资源被分成了多个层次,一个进程得到某一次的一个资源后,** 它只能再申请较高一层的资源** ;当一个进程要释放某层的一个资源时,必须先释放所占用的** 较高层的资源** ,按这种策略,是不可能出现** 循环等待链的** ,因为那样的话,就出现了已经申请了较高层的资源,反而去申请了较低层的资源,不符合** 层次分配策略** ,证明略。
183
+
184
+ #### 死锁的避免
185
+
186
+ 上面提到的** 破坏** 死锁产生的四个必要条件之一就可以成功** 预防系统发生死锁** ,但是会导致** 低效的进程运行** 和** 资源使用率** 。而死锁的避免相反,它的角度是允许系统中** 同时存在四个必要条件** ,只要掌握并发进程中与每个进程有关的资源动态申请情况,做出** 明智和合理的选择** ,仍然可以避免死锁,因为四大条件仅仅是产生死锁的必要条件。
187
+
188
+ 我们将系统的状态分为** 安全状态** 和** 不安全状态** ,每当在未申请者分配资源前先测试系统状态,若把系统资源分配给申请者会产生死锁,则拒绝分配,否则接受申请,并为它分配资源。
189
+
190
+ ` 安全状态 ` :如果操作系统能够保证** 所有的进程在有限的时间内得到需要的全部资源** ,则称系统处于安全状态,否则说系统是不安全的。很显然,` 系统处于安全状态则不会发生死锁,系统若处于不安全状态则可能发生死锁 ` 。
191
+
192
+ 那么如何保证系统保持在安全状态呢?通过算法,其中最具有代表性的** 避免死锁算法** 就是Dijkstra的银行家算法,银行家算法用一句话表达就是,“当一个进程申请使用资源的时候,** 银行家算法** 通过先** 试探** 分配给该进程资源,然后通过** 安全性算法** 判断分配后系统是否处于安全状态,若不安全则试探分配作废,让该进程继续等待,若能够进入到安全的状态,则就** 真的分配资源给该进程** ”。
193
+
194
+ 银行家算法详情可见[ (41条消息) 一句话+一张图说清楚——银行家算法_土豆洋芋山药蛋的博客-CSDN博客_银行家算法] ( https://blog.csdn.net/qq_33414271/article/details/80245715 )
195
+
196
+ 操作系统教程树中讲述的银行家算法也比较清晰,可以一看.
197
+
198
+ 死锁的避免(银行家算法)改善解决了** 资源使用率低的问题** ,但是它要不断地检测每个进程对各类资源的占用和申请情况,以及做** 安全性检查** ,需要花费较多的时间。
199
+
200
+ #### 死锁的检测
201
+
202
+ 对资源的分配加以限制可以** 预防和避免** 死锁的发生,但是都不利于各进程对系统资源的** 充分共享** 。解决死锁问题的另一条途径是** 死锁检测和解除** (这里突然联想到了乐观锁和悲观锁,感觉死锁的检测和解除就像是** 乐观锁** ,分配资源时不去提前管会不会发生死锁了,等到真的死锁出现了再来解决嘛,而** 死锁的预防和避免** 更像是悲观锁,总是觉得死锁会出现,所以在分配资源的时候就很谨慎)。
203
+
204
+ 这种方法对资源的分配不加以任何限制,也不采取死锁避免措施,但系统** 定时地运行一个 “死锁检测”** 的程序,判断系统内是否出现死锁,如果检测到系统发生了死锁,再采取措施去解除它。
205
+
206
+ ##### 进程-资源分配图
207
+
208
+ 操作系统中的每一刻时刻的** 系统状态** 都可以用** 进程-资源分配图** 来表示,进程-资源分配图是描述进程和资源申请及分配关系的一种有向图,可用于** 检测系统是否处于死锁状态** 。
209
+
210
+ 用一个方框表示每一个资源类,方框中的黑点表示该资源类中的各个资源,每个键进程用一个圆圈表示,用** 有向边** 来表示** 进程申请资源和资源被分配的情况** 。约定$P_ {i} \rightarrow R_ {j}$为请求边,表示线程$P_ {i}$申请资源类$R_ {j}$中的一个资源** 得不到满足** 而处于等待$R_ {j}$类资源的状态,该有向边从进程开始指到方框的边缘,表示进程$P_ {i}$申请$R_ {j}$类中的一个资源。反之,$R_ {j}\rightarrow P_ {i}$为** 分配边** ,表示R的一个资源分配给了P。
211
+
212
+ 图中2-21是** 进程-资源分配图** 的一个例子,其中公有三个资源类,每个进程的资源占有和申请情况已清楚地表示在图中。在这个例子中,由于存在** 占有和等待资源的环路** ,导致一组进程永远处于等待资源的状态,** 发生了死锁** 。
213
+
214
+ <img src =" https://github.com/zhengjianda/JavaGuide/blob/main/docs/cs-basics/operating-system/images/%E8%BF%9B%E7%A8%8B-%E8%B5%84%E6%BA%90%E5%88%86%E9%85%8D%E5%9B%BE.jpg " height =" 300 " ></img >
215
+
216
+
217
+ 进程-资源分配图中存在环路** 并不一定是** 发生了死锁。因为循环等待资源仅仅是死锁发生的必要条件,而不是充分条件。图2-22便是一个有环路而无死锁的例子。虽然进程P1和进程P3分别占用了一个资源R1和一个资源R2,并且因为等待另一个资源R2和另一个资源R1形成了环路,但进程P2和进程P4分别占有了一个资源R1和一个资源R2,它们申请的资源得到了满足,在有限的时间里会归还资源,于是进程P1或P3都能获得另一个所需的资源,环路自动解除,系统也就不存在死锁状态了。
218
+
219
+ ##### 死锁检测步骤:
220
+
221
+ 知道了死锁检测的原理,我们可以利用下列步骤编写一个** 死锁检测** 程序,检测系统是否产生了死锁。
222
+
223
+ 1 ) 如果进程-资源分配图中无环路,则此时系统没有发生死锁
224
+ 2 ) 如果进程-资源分配图中有环路,且每个资源类仅有一个资源,则系统中已经发生了死锁。
225
+ 3 ) 如果进程-资源分配图中有环路,且涉及到的资源类有多个资源,此时系统未必会发生死锁。如果能在进程-资源分配图中找出一个** 既不阻塞又非独立的进程** ,该进程能够在有限的时间内归还占有的资源,也就是把边给消除掉了,重复此过程,直到能在有限的时间内** 消除所有的边** ,则不会发生死锁,否则会发生死锁。(消除边的过程类似于** 拓扑排序** )
226
+
227
+ #### 死锁的解除
228
+
229
+ 当死锁检测程序检测到** 存在死锁发生时** ,应设法让其解除,让系统从死锁状态中恢复过来,常用的解除死锁的方法有以下四种:
230
+
231
+ 1 . ** 立即结束所有进程的执行,重新启动操作系统**
232
+
233
+ 这种方法简单,但以前所在的工作全部作废,损失很大。
234
+
235
+ 2 . ** 撤销涉及死锁的所有进程** ,解除死锁后继续运行
236
+
237
+ 这种方法能彻底打破** 死锁的循环等待** 条件,但将付出很大代价,例如有些进程可能已经计算了很长时间,由于被撤销而使产生的部分结果也被消除了,再重新执行时还要再次进行计算。
238
+
239
+ 3 . 逐个撤销涉及死锁的进程,回收其资源直至死锁解除。
240
+
241
+ 4 . 抢占资源:从涉及死锁的** 一个或几个进程** 中抢占资源,把夺得的资源再分配给涉及死锁的进程直至死锁解除。
242
+
156
243
## 三 操作系统内存管理基础
157
244
158
245
### 3.1 内存管理介绍
0 commit comments