操作系统7:进程死锁

news2024/11/27 10:32:27

目录

1、死锁概述

(1)计算机中的资源分类

1.1 - 可重用性资源和消耗性资源

1.2 - 可抢占性资源和不可抢占性资源

(2)计算机系统中的死锁

(3)死锁的定义、必要条件和处理方法

3.1 - 死锁的定义

3.2 - 产生死锁的必要条件

3.3 - 处理死锁的方法

2、如何预防死锁?

(1)破坏“请求和保持”条件

1.1 - 一次性获取所需的全部资源

1.2 - 只获取部分资源即运行

(2)破坏“不可抢占”条件

(3)破坏“循环等待”条件

3、如何避免死锁?

(1)系统安全状态

1.1 - 安全状态

1.2 - 安全状态之例

(2)利用银行家算法避免死锁

4、死锁的检测与解除

(1)死锁的检测

(2)死锁的解除


1、死锁概述

(1)计算机中的资源分类

        在系统中有许多不同类型的资源,其中可以引起死锁的主要是,采用互斥访问、不可以被抢占的资源,即临界资源。系统中这类资源有很多,如打印机、数据文件、队列、信号量等。

1.1 - 可重用性资源和消耗性资源

  • 可重用性资源是一种可供用户重复使用多次的资源。每一个可重用性资源中的单元只能分配给一个进程使用,不允许多个进程共享。进程在使用可重用性资源时,必须遵循先请求资源,然后使用资源,最后释放资源的顺序。系统中每一类可重用性资源中的单元数目是相对固定的,进程在运行期间既不能创建也不能删除它。
  • 可消耗性资源又称为临时性资源,它是在进程运行期间,由进程动态地创建和消耗的。最典型的可消耗性资源就是用于进程间通信的消息等。

1.2 - 可抢占性资源和不可抢占性资源

  • 可抢占性资源,是指某进程在获得这类资源后,该资源可以再被其它进程或系统抢占。CPU 和主存均属于可抢占性资源,对于这类资源是不会引起死锁的。
  • 不可抢占性资源,即一旦系统把某资源分配给该进程后,就不能将它强行收回,只能在进程用完后自行释放。例如,当一个进程已开始刻录光盘时,如果突然将刻录机分配给另一个进程,其结果必然会损坏正在刻录的光盘,因此只能等刻好光盘后由进程自己释放刻录机。另外磁带机、打印机等也都属于不可抢占性资源。

(2)计算机系统中的死锁

        死锁的起因,通常是源于多个进程对资源的争夺,不仅对不可抢占资源进行争夺时会引起死锁,而且对可消耗资源进行争夺时,也会引起死锁。

        上图中,m1,m2 和 m3 是可消耗资源。进程 P1 一方面产生消息 m1,利用 send(p2,m1) 原语将它发送给 P2;另一方面,它又要求从 P3 接收消息 m3,而进程 P2 一方面产生消息 m2,利用 send(p3,m3) 原语将它发送给 P3,另一方面它又需要接收进程 P1 所产生的消息 m1。类似地,进程 P3 也产生消息 m3,利用 send(p1,m3) 原语将它发送给 P1,而它又要求从进程 P2 接收其所产生的消息 m2。如果三个进程间的消息通信,按下述顺序进行:// 三个资源的闭环

P1: ...send(p2,m1);  receive(p3,m3);  ...
P2: ...send(p3,m2);  receive(p1,m1);  ...
P3: ...send(p1,m3);  receive(p2,m2);  ...

        如果这三个进程都可以先将消息发送给下一个进程,相应地它们也都能够接收到从上一个进程发来的消息,因此三个进程可以顺利地运行下去,而不会发生死锁。但若改成三个进程都先执行 receive 操作,后执行 send 操作,即按下述的运行顺序:

P1: ...receive(p3,m3);  ...send(p2,m1);  
P2: ...receive(p1,m1);  ...send(p3,m2);
P3: ...receive(p2,m2);  ...send(p1,m3);    

        则这三个进程就会永远阻塞在它们的 receive 操作上,等待一条永远不会发出的消息,于是发生了死锁。// 这个例子有点绕,但是很好的阐释了可消耗资源引起的死锁问题

(3)死锁的定义、必要条件和处理方法

3.1 - 死锁的定义

        在一组进程发生死锁的情况下,这组死锁进程中的每一个进程,都在等待另一个死锁进程所占有的资源。由于所有这些进程已都无法运行,因此它们谁也不能释放资源,致使没有任何一个进程可被唤醒。这样这组进程只能无限期地等待下去。

        所以,如果一组进程中的每一个进程都在等待仅由该组进程中的其它进程才能引发的事件,那么该组进程是死锁的(DeadLock)。//比较拗口,简单的来说就是都在无限期的等待资源

3.2 - 产生死锁的必要条件

        虽然进程在运行过程中可能会发生死锁,但产生进程死锁是必须具备一定条件的。产生死锁必须同时具备下面四个必要条件,只要其中任一个条件不成立,死锁就不会发生:

  • 互斥条件。进程对所分配到的资源进行排它性使用,即在一段时间内,某资源只能被一个进程占用。如果此时还有其它进程请求该资源,则请求进程只能等待,直至占有该资源的进程释放。
  • 请求和保持条件。进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
  • 不可抢占条件。进程已获得的资源在未使用完之前不能被抢占,只能在进程使用完时由自己释放。
  • 循环等待条件。在发生死锁时,必然存在一个进程和资源的循环链。

3.3 - 处理死锁的方法

        目前处理死锁的方法可归结为四种:

  • 预防死锁。这是一种较简单和直观的事先预防方法。该方法是通过设置某些限制条件,去破坏产生死锁四个必要条件中的一个或几个来预防产生死锁。预防死锁是一种较易实现的方法,已被广泛使用。
  • 避免死锁。同样是属于事先预防策略,但它并不是事先采取各种限制措施,去破坏产生死锁的四个必要条件,而是在资源的动态分配过程中,用某种方法防止系统进入不安全状态,从而可以避免发生死锁。
  • 检测死锁。这种方法无须事先采取任何限制性措施,允许进程在运行过程中发生死锁。但可通过检测机构及时地检测出死锁的发生,然后采取适当的措施,把进程从死锁中解脱出来。
  • 解除死锁。当检测到系统中已发生死锁时,就采取相应措施,将进程从死锁状态中解脱出来。常用的方法是撤消一些进程,回收它们的资源,将它们分配给已处于阻塞状态的进程,使其能继续运行。

        上述的四种方法,从上到下对死锁的防范程度逐渐减弱,但对应的是资源利用率的提高,以及进程因资源因素而阻塞的频度下降(即并发程度提高)。//两全不能其美

2、如何预防死锁?

        预防死锁的方法是通过破坏产生死锁的四个必要条件中的一个或几个,以避免发生死锁。由于互斥条件是非共享设备所必须的,不仅不能改变,还应加以保证,因此主要是破坏产生死锁的后三个条件。

(1)破坏“请求和保持”条件

        为了能破坏“请求和保持”条件,系统必须保证做到:当一个进程在请求资源时,它不能持有不可抢占资源。该保证可通过如下两个不同的方式实现:

1.1 - 一次性获取所需的全部资源

        使用该方式,所有进程在开始运行之前,必须一次性地申请其在整个运行过程中所需的全部资源。此时若系统有足够的资源分配给某进程,便可把其需要的所有资源分配给它。这样,该进程在整个运行期间,便不会再提出资源要求,从而破坏了“请求”条件。系统在分配资源时,只要有一种资源不能满足进程的要求,即使其它所需的各资源都空闲也不分配给该进程,而让该进程等待。由于该进程在等待期间未占有任何资源,于是破坏了“保持”条件,从而可以预防死锁的发生。

        该方式的优点是简单、易行且安全。但缺点也极其明显:

  • 资源被严重浪费,严重地恶化了资源的利用率。进程在开始运行时就一次性地占用了整个运行过程所需的全部资源,其中有些资源可能仅在运行初期或运行快结束时才使用,甚至根本不使用。
  • 使进程经常会发生饥饿现象。因为仅当进程在获得了其所需的全部资源后才能开始运行,这样就可能由于个别资源长期被其它进程占用,而致使等待该资源的进程迟迟不能开始运行,而个别资源有可能仅在进程运行到最后才需要,如打印机往往就是如此。

1.2 - 只获取部分资源即运行

        该方式是对第一种方式的改进,它允许一个进程只获得运行初期所需的资源后,便开始运行。进程运行过程中再逐步释放已分配给自己的、且已用毕的全部资源,然后再请求新的所需资源。

        我们可以通过一个具体例子来说明,第二种方式比第一种方式要好。

        例如,有一个进程,它所要完成的任务是,先将数据从磁带上复制到磁盘文件上,然后对磁盘文件进行排序,最后把结果打印出来。在采用第一种方式时,进程必须在开始时就请求磁带机、磁盘文件和打印机。然而打印机仅在最后才会用到,既影响到其利用率,还会影响到其它进程的运行。此外,又如磁带机和磁盘文件虽然空闲,但因打印机已分配给其它进程因而进程还需要等待。// 第一种方式:必须拥有:磁带机+磁盘文件+打印机

        在采用第二种方式时,进程在开始时只需请求磁带机、磁盘文件,然后就可运行。等到全部磁带上的数据已复制到磁盘文件中并已排序好后,便可将磁带机和磁盘文件释放掉再去请求磁盘文件和打印机。这不仅能使进程更快地完成任务,提高设备的利用率,还可减少进程发生饥饿的机率。// 第二种方式:先拥有:磁带机+磁盘文件,然后再申请打印机

(2)破坏“不可抢占”条件

        破坏“不可抢占”条件,即当一个已经保持了某些不可被抢占资源的进程,提出新的资源请求而不能得到满足时,它必须释放已经保持的所有资源,待以后需要时再重新申请。这意味着进程已占有的资源会被暂时地释放,或者说是被抢占了,从而破坏了“不可抢占”条件。//不能一直持有资源

        该方式实现起来比较复杂,且需付出很大的代价。因为一个不可抢占的资源如打印机、CD 刻录机等在使用一段时间后被抢占,可能会造成进程前一阶段工作的失效,即使是采取了某些防范措施,也还会使进程前后两次运行的信息不连续。这种策略还可能因为反复地申请和释放资源致使进程的执行被无限地推迟,这不仅延长了进程的周转时间,而且也增加了系统开销,降低了系统吞吐量。//破坏不可抢占条件,代价比较大

(3)破坏“循环等待”条件

        为了能保证“循环等待”条件不成立,需要对系统所有资源类型进行线性排序并赋予不同的序号。在对系统所有资源类型进行线性排序后,规定每个进程必须按序号递增的顺序请求资源。如果需要多个同类资源单元,则必须一起请求//破环进程和资源的环路

        在采用这种策略时,请求资源的顺序是十分重要的。一般情况下,进程总是先输入程序和数据,继而进行运算,最后将计算结果输出。故可以要求先获取输入设备(磁带机),然后再获取输出设备(打印机)。

        这种预防死锁的策略与前两种策略比较,其资源利用率和系统吞吐量都有较明显的改善。但也存在下述问题:

  • 首先,为系统中各类资源所规定的序号必须相对稳定,这就限制了新类型设备的增加
  • 其次,如果作业使用各类资源的顺序与系统规定的顺序不同,会造成对资源的浪费
  • 第三,为方便用户,系统对用户在编程时所施加的限制条件应尽量少,然而这种按规定次序申请资源的方法必然会限制用户简单、自主地编程

3、如何避免死锁?

        避免死锁同样是属于事先预防的策略,但并不是事先采取某种限制措施,破坏产生死锁的必要条件,而是在资源动态分配过程中,防止系统进入不安全状态,以避免发生死锁。这种方法所施加的限制条件较弱,可能获得较好的系统性能,目前常用此方法来避免发生死锁。

(1)系统安全状态

        在死锁避免方法中,把系统的状态分为安全状态和不安全状态。当系统处于安全状态时,可避免发生死锁。反之,当系统处于不安全状态时,则可能进入到死锁状态。

1.1 - 安全状态

        在该方法中,允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次资源分配的安全性。若此次分配不会导致系统进入不安全状态,才可将资源分配给进程,否则,令进程等待。

        所谓安全状态,是指系统能按某种进程推进顺序(P1,P2,...,Pn)为每个进程 Pi 分配其所需资源,直至满足每个进程对资源的最大需求,使每个进程都可顺利地完成。此时称(P1,P2,...,Pn)为安全序列。如果系统无法找到这样一个安全序列,则称系统处于不安全状态。

        虽然并非所有不安全状态都必然会转为死锁状态,但当系统进入不安全状态后,就有可能进入死锁状态。反之,只要系统处于安全状态,系统便不会进入死锁状态。因此,避免死锁的实质在于,系统在进行资源分配时,应使系统不进入不安全状态// 能分配的资源是否足够,如果不足够,那么系统就是不安全的

1.2 - 安全状态之例

        假定系统中有三个进程 P1、P2 和 P3,共有 12 台磁带机。进程 P1 总共要求 10 台磁带机,P2 和 P3 分别要求 4 台和 9 台。假设在 T0 时刻,进程 P1、P2 和 P3 已分别获得 5 台、2 台和 2 台磁带机,尚有 3 台空闲未分配,如下表所示:

        经分析发现,在 T0 时刻系统是安全的,因为这时存在一个安全序列(P2,P1,P3),即只要系统按此进程序列分配资源,就能使每个进程都顺利完成。例如,将剩余的磁带机取 2 台分配给 P2,使之继续运行,待 P2 完成便可释放出 4 台磁带机,于是可用资源增至 5 台;以后再将这些全部分配给进程 P1,使之运行,待 P1 完成后,将释放出 10 台磁带机,P3 便能获得足够的资源,从而使 P1、P2、P3 每个进程都能顺利完成。// 所谓安全序列,就是使每一进程都能获得足够资源的运行顺序

(2)利用银行家算法避免死锁

        银行家算法的思想:每当一个新进程在进入系统时,它必须申明在运行过程中,可能需要每种资源类型的最大单元数目,其数目不应超过系统所拥有的资源总量。当进程请求一组资源时,系统必须首先确定是否有足够的资源分配给该进程。若有,再进一步计算在将这些资源分配给进程后,是否会使系统处于不安全状态。如果不会,才将资源分配给它,否则让进程等待。

// 总结:避免的死锁的核心思想,就是在资源动态分配过程中,防止系统进入不安全状态,也就是保障系统中有足够的资源。

// 必要时,手动实现下这个算法的逻辑

4、死锁的检测与解除

        如果在系统中,既不采取死锁预防措施,也未配有死锁避免算法,系统很可能会发生
死锁。在这种情况下,系统应当提供两个算法:

  • 死锁检测算法。该方法用于检测系统状态,以确定系统中是否发生了死锁。
  • 死锁解除算法。当认定系统中已发生了死锁,利用该算法可将系统从死锁状态中解脱出来。

(1)死锁的检测

        为了能对系统中是否已发生了死锁进行检测,在系统中必须

  • 保存有关资源的请求和分配信息。
  • 提供一种算法,它利用这些信息来检测系统是否已进入死锁状态。

//书中使用资源分配图作为例子,在此,不做过多描述,有兴趣看书

(2)死锁的解除

        如果利用死锁检测算法检测出在系统中已发生了死锁,则应立即采取相应的措施,以解除死锁。

        最简单的处理措施就是立即通知操作员,请操作员来以人工方法处理死锁

        另一种措施则是利用死锁解除算法,把系统从死锁状态中解脱出来。常采用解除死锁的两种方法是:// 自动解决死锁问题

  • 抢占资源。从一个或多个进程中抢占足够数量的资源,分配给死锁进程,以解除死锁状态。
  • 终止(或撤消)进程。终止(或撤消)系统中的一个或多个死锁进程,直至打破循环环路,使系统从死锁状态解脱出来。

        终止进程的方法有两种:终止所有死锁进程逐个终止进程。终止所有死锁进程比较简单粗暴,全部终止即可。逐个终止进程方式,会考虑到进程终止的代价,终止进程时也会考虑进程的优先级,资源利用情况等,没有一个精确的度量标准,总之会比较复杂。//考虑终止代价最小化

// 在计算机中,所有求最优解的一个最大的问题是,计算机里边的东西是动态的,而我们往往使用静态的方式去思考问题,最终的结果就是,解决问题的方法很片面,或者说只能理论上可行。

// 比如,限定在一组数中去求解,对有限的数据进行分析,而实际情况却比这要复杂得多。事实是,我们不可能去全量论证一个问题的解,只能通过把动态的东西静态化,把复杂的东西简单化,一步一步去求解和探索规律。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/720236.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

运输层:TCP拥塞控制

1.运输层:TCP拥塞控制 笔记来源: 湖科大教书匠:TCP的拥塞控制 声明:该学习笔记来自湖科大教书匠,笔记仅做学习参考 网络资源:在计算机网络中的链路容量(即带宽)、交换结点中的缓存和…

windows 10 安装Python 3.10版

一、查找官网 1.python官网需要VPN(建立一个临时的、安全的连接,是一条穿过混乱的公用网络的安全、稳定的隧道。),打开VPN进行代理之后,打开网址:https://www.python.org/ 二、查找所需下载的系统及版本 1.本机是winodws操作系统&…

计算机网络_ 1.3 网络核心 (数据交换_报文、分组交换)

计算机网络_数据交换_报文、分组交换 报文交换(message switching)分组交换(package switching)存储-转发(store-and-forward)传输延迟分组交换的报文交付时间 分组交换 vs 电路交换 报文交换(m…

zabbix监控部署(都是导图!)

目录 一:监控软件的作用 二:zabbix 简介 1、zabbix 概述 2、zabbix 监控原理 3、 Zabbix 6.0 新特性 (1)Zabbix server高可用防止硬件故障或计划维护期的停机 (2)Zabbix 6.0 LTS新增Kubernetes监控功…

C语言入门篇(二)

前言   续接上一篇文章,此篇继续对C语言的基础知识点进行更新。 C语言入门篇(一) 初始C语言 7. 选择语句8. 循环语句9. 函数9.1 函数的定义9.2 函数的调用 10. 数组10.1 数组定义10.2 数组的下标10.3 数组的使用 11. 操作符12.…

JAVA学习(九)

1.java锁 1.1 AtomicInteger 首先说明,此处 AtomicInteger,一个提供原子操作的 Integer 的类,常见的还有 AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference 等,他们的实现原理相同, 区别在与运算对象类型…

搭建新版security-oauth2协议,流程代码详解,源码分析

前言:最近在学习搭建oauth2协议的开放平台,把搭建框架时的思路以及遇到的问题记录下来。 文章会持续更新,前期可能会比较零碎,最后会整合一起,写一篇从部署到使用、踩坑、依赖版本解决等完整文章。 使用的是Spring S…

【深度学习】深度强化学习初学者指南

一、说明 GAN(Generative Adversarial Networks)是一种深度学习模型,它由两个神经网络组成:一个生成网络和一个判别网络。生成网络学习如何生成类似于给定数据集的新数据,而判别网络则学习如何区分生成网络生成的数据和…

Linux下的基本指令

Linux下的基本指令 操作系统的概念01.adduser指令02.userdel指令03.pwd指令04.ls指令05.tree指令06.cd指令07.touch指令08.mkdir指令(重要)09.rmdir指针&&rm指令(重要)10.man指针(重要)11.cp指令&a…

【macOS 系列】如何调整启动台图标大小和行数

1、使用指令,这是隐藏的技巧,在控制台输入如下指令 defaults write com.apple.dock springboard-rows -int 6 defaults write com.apple.dock springboard-columns -int 8 defaults write com.apple.dock ResetLaunchPad -bool TRUE killall Dock以上表…

基于Web的智慧交通3D可视化系统

前言 城市交通是城市社会活动、经济活动的纽带和动脉,智慧交通系统对城市经济发展和人民生活水平起着极其重要的作用。 背景 随着我国城市化进程不断加快,现代城市交通问题日益受到人们的关注。特别是汽车数量的与日俱增,给城市带来了大量…

Socket介绍及使用Java实现socket通信

一、Socket概述 Socket(套接字)是计算机网络编程中用于实现网络通信的一种机制。它提供了一种编程接口,允许应用程序通过网络进行数据传输,实现不同主机之间的通信。 Socket可以看作是一种抽象的概念,用于描述网络通信…

性能监控软件的软件特色有哪些?

性能监控软件是一种专门用于监测和分析系统性能的软件工具。它可以帮助开发人员、运维人员和系统管理员追踪系统的性能瓶颈,优化系统性能,提供稳定可靠的服务,那性能监控软件的软件特色有哪些? 实时监控:性能监控软件可…

3、CCesium 第一个地图

1、将下载的CCsium库解压到指定目录如D:/install,里面有几个文件 bin:导出的dll examples:一个简单的示例 include:ccesium和第三方库的头文件 lib:搜索cceisum库的一些信息 share:一些说明 我们主要用…

allatori-JAVA代码混淆工具

Allatori是第二代Java混淆器,它为您的知识产权提供全方位的保护。 虽然大多数第二代混淆器都能提供值得信赖的保护,但我们在Allatori中开发了一些额外的功能,使代码的反向工程几乎不可能。 Allatori不仅仅是混淆,它还能最大限度…

为什么你感觉中层管理一直闲着没事干?

点击下方“JavaEdge”,选择“设为星标” 第一时间关注技术干货! 免责声明~ 切记,任何文章不要过度深思(任何东西都无法经得起审视,因为这世上没有同样的成长环境,也没有同样的认知水平同时也「没有适用于所…

eNSP的使用

目录 配置路由器 DHCP——动态主机配置协议 工作过程: 第一种场景——PC首次获取IP地址的情况 第二种场景——pc(客户都)再次获取IP地址的情况 DHCP配置: Telnet 搭建好图后 1.看广播域(路由器有几个接口就有几…

在树莓派上搭建web站点并发布互联网上线【无需公网IP】

文章目录 概述使用 Raspberry Pi Imager 安装 Raspberry Pi OS设置 Apache Web 服务器测试 web 站点安装静态样例站点将web站点发布到公网安装 Cpolar内网穿透cpolar进行token认证生成cpolar随机域名网址生成cpolar二级子域名将参数保存到cpolar配置文件中测试修改后配置文件配…

JUC--CompletableFuture下

对计算速度进行选用 import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit;public class Test4 {public static void main(String[] args) {CompletableFuture<String> a CompletableFuture.supplyAsync(() -> {try { TimeUnit.SE…

list和vector容器的插入与访问操作区别

文章目录 list插入元素和vector插入元素对比案例vector的做法list优化的做法为什么时间复杂度相同还会有性能差异 std::list和std::vector是C中的两种常见数据结构&#xff0c;它们在不同的使用场景下各有优势。 std::vector的内部实现是动态数组&#xff0c;它在连续的内存块…