首页 > 其他分享 >第六章 死锁

第六章 死锁

时间:2024-08-03 11:28:54浏览次数:19  
标签:抢占 请求 进程 死锁 第六章 等待 资源

第六章 死锁

6.1 资源

资源就是随着时间的推移, 必须能获得、 使用以及释放的任何东西。

6.1.1 可抢占资源和不可抢占资源

资源分为两类: 可抢占的和不可抢占的。 可抢占资源(preemptable resource) 可以从拥有它的进程中抢占而不会产生任何副作用, 存储器就是一类可抢占的资源。

不可抢占资源(nonpreemptable resource) 是指在不引起相关的计算失败的情况下, 无法把它从占有它的进程处抢占过来。

总的来说, 死锁和不可抢占资源有关, 有关可抢占资源的潜在死锁通常可以通过在进程之间重新分配资源而化解。 所以, 我们的重点放在不可抢占资源上。

使用一个资源所需要的事件顺序可以用抽象的形式表示如下:

  1. 请求资源。
  2. 使用资源。
  3. 释放资源。

6.2 死锁简介

如果一个进程集合中的每个进程都在等待只能由该进程集合中的其他进程才能引发的事件, 那么, 该进程集合就是死锁的。

6.2.1 资源死锁的条件

死锁的四个必要条件:

  1. 互斥条件。 每个资源要么已经分配给了一个进程, 要么就是可用的。
  2. 占有和等待条件。 已经得到了某个资源的进程可以再请求新的资源。
  3. 不可抢占条件。 已经分配给一个进程的资源不能强制性地被抢占, 它只能被占有它的进程显式地释放。
  4. 环路等待条件。 死锁发生时, 系统中一定有由两个或两个以上的进程组成的一条环路, 该环路中的每个进程都在等待着下一个进程所占有的资源。

6.2.2 死锁建模

有四种处理死锁的策略:

  1. 忽略该问题。 也许如果你忽略它, 它也会忽略你。
  2. 检测死锁并恢复。 让死锁发生, 检测它们是否发生, 一旦发生死锁, 采取行动解决问题。
  3. 仔细对资源进行分配, 动态地避免死锁。
  4. 通过破坏引起死锁的四个必要条件之一, 防止死锁的产生。

请添加图片描述

6.3 鸵鸟算法

最简单的解决方法是鸵鸟算法: 把头埋到沙子里, 假装根本没有问题发生 。

6.4 死锁检测和死锁恢复

第二种技术是死锁检测和恢复。 在使用这种技术时, 系统并不试图阻止死锁的产生, 而是允许死锁发生, 当检测到死锁发生后, 采取措施进行恢复。 本节我们将考察检测死锁的几种方法以及恢复死锁的几种方法。

6.4.1 每种类型一个资源的死锁检测

这一算法是依次将每一个节点作为一棵树的根节点, 并进行深度优先搜索。 如果再次碰到已经遇到过的节点, 那么就算找到了一个环。 如果从任何给定的节点出发的弧都被穷举了, 那么就回溯到前面的节点。 如果回溯到根并且不能再深入下去, 那么从当前节点出发的子图中就不包含任何环。 如果所有的节点都是如此, 那么整个图就不存在环, 也就是说系统不存在死锁。

请添加图片描述

6.4.2 每种类型多个资源的死锁检测

如果有多种相同的资源存在, 就需要采用另一种方法来检测死锁。 现在我们提供一种基于矩阵的算法来检测从P1 到Pn 这n个进程中的死锁。 假设资源的类型数为m, E1 代表资源类型1, E2 代表资源类型2, Ei 代表资源类型i(1≤i≤m)。 E是现有资源向量(existing resource vector) , 代表每种已存在的资源总数。 比如, 如果资源类型1代表磁带机, 那么E1 =2就表示系统有两台磁带机。

在任意时刻, 某些资源已被分配所以不可用。 假设A是可用资源向量(available resource vector) , 那么Ai 表示当前可供使用的资源数(即没有被分配的资源) 。 如果仅有的两台磁带机都已经分配出去了, 那么A1 的值为0。

现在我们需要两个数组: C代表当前分配矩阵(current allocation matrix) , R代表请求矩阵(request matrix) 。 C的第i行代表Pi 当前所持有的每一种类型资源的资源数。 所以, Cij 代表进程i所持有的资源j的数量。 同理, Rij 代表Pi 所需要的资源j的数量。 这四种数据结构如图6-6所示。

请添加图片描述

这四种数据结构之间有一个重要的恒等式。 具体地说, 某种资源要么已分配要么可用。 这个结论意味着:

请添加图片描述

换言之, 如果我们将所有已分配的资源j的数量加起来再和所有可供使用的资源数相加, 结果就是该类资源的资源总数。

请添加图片描述

第1个不能被满足, 因为没有CDROM驱动器可供使用。

第2个也不能被满足, 由于没有打印机空闲。 幸运的是, 第3个可被满足, 所以进程3运行并最终释放它所拥有的资源, 给出

​ A=(2 2 2 0)

接下来, 进程2也可运行并释放它所拥有的资源, 给出

​ A=(4 2 2 1)

现在剩下的进程都能够运行, 所以这个系统中不存在死锁。

6.4.3 从死锁中恢复

利用抢占恢复

在某些情况下, 可能会临时将某个资源从它的当前所有者那里转移到另一个进程。 许多情况下, 尤其是对运行在大型主机上的批处理操作系统来说, 需要人工进行干预。

利用回滚恢复

一旦检测到死锁, 就很容易发现需要哪些资源。 为了进行恢复, 要从一个较早的检查点上开始, 这样拥有所需要资源的进程会回滚到一个时间点, 在此时间点之前该进程获得了一些其他的资源。

通过杀死进程恢复

最直接也是最简单的解决死锁的方法是杀死一个或若干个进程。 一种方法是杀掉环中的一个进程。 如果走运的话,

6.5 死锁避免

6.5.1 资源轨迹图

避免死锁的主要算法是基于一个安全状态的概念。

请添加图片描述

6.5.2 安全状态和不安全状态

如果没有死锁发生, 并且即使所有进程突然请求对资源的最大需求, 也仍然存在某种调度次序能够使得每一个进程运行完毕, 则称该状态是安全的。

安全状态和不安全状态的区别是: 从安全状态出发, 系统能够保证所有进程都能完成;
请添加图片描述

而从不安全状态出发, 就没有这样的保证。

请添加图片描述

6.5.3 单个资源的银行家算法

银行家算法就是对每一个请求进行检查, 检查如果满足这一请求是否会达到安全状态。 若是, 那么就满足该请求; 若否, 那么就推迟对这一请求的满足。 为了看状态是否安全, 银行家看他是否有足够的资源满足某一个客户。 如果可以, 那么这笔投资认为是能够收回的, 并且接着检查最接近最大限额的一个客户, 以此类推。 如果所有投资最终都被收回, 那么该状态是安全的, 最初的请求可以批准。

请添加图片描述

6.5.4 多个资源的银行家算法

可以把银行家算法进行推广以处理多个资源。

请添加图片描述

6.6 死锁预防

6.6.1 破坏互斥条件

先考虑破坏互斥使用条件。 如果资源不被一个进程所独占, 那么死锁肯定不会产生。

6.6.2 破坏占有并等待条件

只要禁止已持有资源的进程再等待其他资源便可以消除死锁。 一种实现方法是规定所有进程在开始执行前请求所需的全部资源。 如果所需的全部资源可用, 那么就将它们分配给这个进程, 于是该进程肯定能够运行结束。 如果有一个或多个资源正被使用, 那么就不进行分配, 进程等待。

6.6.3 破坏不可抢占条件

破坏第三个条件(不可抢占) 也是可能的。
然而, 并不是所有的资源都可以进行类似的虚拟化。 例如, 数据库中的记录或者操作系统中的表都必须被锁定, 因此存在出现死锁的可能。

6.6.4 破坏环路等待条件

消除环路等待有几种方法。 一种是保证每一个进程在任何时刻只能占用一个资源, 如果要请求另外一个资源, 它必须先释放第一个资源。 但假若进程正在把一个大文件从磁带机上读入并送到打印机打印, 那么这种限制是不可接受的。

另一种避免出现环路等待的方法是将所有资源统一编号, 如图6-13a所示。 现在的规则是: 进程可以在任何时刻提出资源请求, 但是所有请求必须按照资源编号的顺序(升序) 提出。 进程可以先请求打印机后请求磁带机, 但不可以先请求绘图仪后请求打印机。

请添加图片描述

6.7 其他问题

6.7.1 两阶段加锁

常用的方法是两阶段加锁(two-phase locking) 。 在第一阶段, 进程试图对所有所需的记录进行加锁,一次锁一个记录。 如果第一阶段加锁成功, 就开始第二阶段, 完成更新然后释放锁。 在第一阶段并没有做实际的工作。

6.7.2 通信死锁

源死锁是最普遍的一种类型, 但不是惟一的一种。 另一种死锁发生在通信系统中(比如说网络) , 即两个或两个以上进程利用发送信息来通信时。 一种普遍的情形是进程A向进程B发送请求信息, 然后阻塞直至B回复。 假设请求信息丢失, A将阻塞以等待回复, 而B会阻塞等待一个向其发送命令的请求, 因此发生死锁。

根据标准的定义, 在一系列进程中, 每个进程因为等待另外一个进程引发的事件而产生阻塞, 这就是一种死锁。 相比于更加常见的资源死锁, 我们把上面这种情况叫做通信死锁(communication deadlock) 。

另外一种技术通常可以用来中断通信死锁: 超时。

并非所有在通信系统或者网络发生的死锁都是通信死锁。 资源死锁也会发生, 如图6-15中的网络。

请添加图片描述

6.7.3 活锁

在某种情形下, 轮询(忙等待) 可用于进入临界区或存取资源。 采用这一策略的主要原因是, 相比所做的工作而言, 互斥的时间很短而挂起等待的时间开销很大。

6.7.4 饥饿

在动态运行的系统中, 在任何时刻都可能请求资源。 这就需要一些策略来决定在什么时候谁获得什么资源。 虽然这个策略表面上很有道理, 但依然有可能使一些进程永远得不到服务, 虽然它们并不是死锁进程。

标签:抢占,请求,进程,死锁,第六章,等待,资源
From: https://blog.csdn.net/wgy17734894660/article/details/140887519

相关文章

  • ffmpeg python 导致死锁
    我在使用ffmpegpython处理相机帧时遇到问题。我使用process.communicate()的第一种方法效果很好,但存在延迟问题。process=(ffmpeg.input('pipe:',format='rawvideo',pix_fmt='rgb24',s='{}x{}'.format(width,height))......
  • 【MySQL(锁篇)】深入MySQL锁机制:从全局到行级,解锁数据库性能瓶颈(下:行锁分析实战、死锁原
    文章目录MySQL(锁篇)-全局锁、表锁、行锁(记录锁、间隙锁、临键锁、插入意向锁)、意向锁、SQL加锁分析、死锁产生原因与排查行锁分析实战1读已提交RC1.1组合一:ID是主键1.2组合二:ID唯一索引1.3组合三:ID非唯一索引1.4组合四:ID无索引2可重复读RR2.1组合五:ID主键2.2组......
  • JavaEE 初阶(7)——多线程5之线程安全中 -->“死锁”
    目录一.什么是“死锁”二.产生死锁的场景  场景1:一个线程连续加锁 场景2:两个线程两把锁场景3:N个线程M把锁 三.产生死锁的四个必要条件(缺一不可)四. Java标准库中的线程安全类一.什么是“死锁”并非是synchronized就一定线程安全,还要看代码具体咋写。到底......
  • 计组笔记第六章——总线
    6.1.1总线概述总线简图:总线的物理实现:“一根”;数据总线可能包含多跟信号线,所有硬件部件都可以通过这跟总线传递数据。同一时刻只能有一个部件发送数据,但可以有多个部件接受数据。基本概念总线的定义:总线是一组能为多个部件分时共享的公共信息传送线路。为什么要用总线......
  • MySQL PXC 集群死锁分析案例
    前不久一个系统死锁导致部分业务受到影响,今次补上详细的节点日志分析过程。这个PXC集群有三个节点,分别是108、109、110,日志信息的ip6地址、节点编号等信息均已做脱敏处理。以下日志里面,3个节点对应的配置信息是:10899999999-99089999:9999:9999:9999::6c10999999999-99099......
  • 死锁-举例
    首先回顾我们对死锁的定义,通俗易懂地说就是双方在占有自己手上的资源时,需要对方手上的资源才能继续下去,但是双方又不愿意主动放弃自己手上的资源用一个生活中通俗易懂的例子就是:对方道歉我就道歉这个模型用代码实现最简单的框架是这样publicclassMustDeadLockimplementsRun......
  • 模块2 面向对象编程初级 --- 第六章:创建对象
    第六章创建对象主要知识点:1、类的实例化2、构造方法3、对象的使用4、对象的清除学习目标:根据定义的类进行实例化,并且运用对象编写代码完成一定的功能。本章对类进行实例化,生成类的对象,利用对象开始软件的设计过程,掌握对象的使用方法。6.1创建对象概......
  • FreeRTOS操作系统(详细速通篇)——— 第六章
        本专栏将对FreeRTOS进行快速讲解,带你了解并使用FreeRTOS的各部分内容。适用于快速了解FreeRTOS并进行开发、突击面试、对新手小白非常友好。期待您的后续关注和订阅!目录系统中断管理1什么是中断?1.1中断定义1.2中断执行机制​2中断优先级如何分组 2.1优先级......
  • 记一个引起MYSQL死锁Deadlock found when trying to get lock; try restarting transac
    一、记一个引起MYSQL死锁Deadlockfoundwhentryingtogetlock;tryrestartingtransaction的例子  今天在尝试MYSQL事务的时候,这种情况总会引起死锁,不知道为什么,我使用的测试MYSQL表的创建SQL如下:CREATETABLE`user`(`id`int(10)unsignedNOTNULLAUTO_INC......
  • 什么是死锁 , 以及产生的原因详细介绍
    死锁一.什么是死锁指的是两个或者两个以上的线程在执行的过程中由于竞争同步锁而产生的一种阻塞现象;如果没有外力的作用,他们将无法继续执行下去,这种情况称之为死锁,通俗的说死锁产生的原因主要是由于线程的相互等待,导致程序无法进行下去二.代码阐述这里我们写......