死锁(知识体系架构和详细解释)
如果觉得翻页太麻烦,看一看右边有目录点击即可跳转
大纲
下面先把死锁的架构搞出来,然后在做详细的解释
计算机系统中有很多独占性资源,同一时刻每个资源只能由一个进程使用,所以操作系统具有授权一个进程单独访问资源的能力。两个进程独占性的访问某个资源,从而等待另外一个资源的执行结果,会导致两个进程都被阻塞,并且两个进程都不会释放各自的资源,这种情况就是 死锁(deadlock)。
死锁可以发生在任何层面,在不同的机器之间可能会发生死锁,在数据库系统中也会导致死锁,比如进程 A 对记录 R1 加锁,进程 B 对记录 R2 加锁,然后进程 A 和 B 都试图把对象的记录加锁,这种情况下就会产生死锁。
资源
资源: 大部分的死锁都和资源有关,在进程对设备、文件具有独占性(排他性)时会产生死锁。对于这类需要排他性使用的对象成为资源。
资源 | |
1 | 可抢占资源 |
2 | 不可抢占资源 |
(1)可抢占资源:可以从它的进程中抢占资源而不会造成其他影响,比如内存就是一种可抢占性资源。
(2)不可抢占资源:除非引起错误和异常,不然进程无法抢占指定资源,比如光盘在进程执行的调度中,其他进程是不能得到的。
死锁一般与不可抢占资源有关,虽然可抢占资源也会造成死锁,不过一般都是用在进程之间重新分配资源来化解。
下面重点讲解不可抢占资源有关
资源所需事件的顺序:
请求资源——————>使用资源——————>释放资源
当请求资源不存在时,请求进程就会强制等待。
请求资源失败的进程会陷入一种请求资源、休眠、在请求资源的循环中,虽然没有阻塞但也差不多,因为这类进程没有做任何有用的工作。
(对理解本文有用){互斥锁:计算机程序中,互斥对象是一个程序对象,它允许多个程序共享同一个资源,例如文件访问权限,但并不是同时访问。需要锁定资源的线程都必须在使用资源时将互斥锁与其它线程绑定(进行加锁),当不在需要数据或线程结束时,互斥锁设置为解锁。}
死锁
简单的定义一下:如果一组进程中的每个程序都在等待一个事件,而这个事件只能由该组中的另一个进程触发,这种情况会导致死锁。
简单来说就是每一个进程都在等待其他进程释放资源,导致没有一个进程释放资源,所有进程都会无限的等下去,从而导致死锁。
下面分为两大块讲,资源死锁的条件和死锁模型
{1}资源死锁的条件
(1)什么是资源死锁?
————死锁进程中的每个进程都在等待另一个死锁进程已经占有的资源,但由于所有进程都不能运行也就无法释放任何资源,同时也没有任何一个进程可以被唤醒,这种死锁同常被称为资源死锁。
(2)资源死锁可能出现的情况
互斥条件:每个资源都被分配 给了一个进程或者资源时可用的
保持和等待条件:已经获取资源的进程被认为能够获取新的资源
不可抢占条件:分配给一个进程的资源不能强制的从其他进程抢占资源,只能由占有他的进程显示释放
循环等待:死锁发生时,系统中一定有两个或者两个以上的进程组成一个循环,循环中的每个进程都在等待下一个进程释放资源。
死锁发生时以上条件必须同时成立,任何一个不成立死锁都不会发生。
{2}死锁模型
一个死锁的过程,进程C等待资源T的释放,但是资源T被进程D占用,进程D在等待请求占用资源U,资源U却已近被线程C占用,从而形成了一个环。
简单的说就是:吃着碗里的看着锅里的容易死锁。
下面就这四种方法仔细讲解一下,请继续看下去。
鸵鸟算法
第一种,在计算机科学中,鸵鸟算法是一个忽略潜在问题的一种算法策略,这种策略对计算机程序可能出现的问题采取无视态度(类似于鸵鸟在遇到危险时将头埋在地里,装作看不见)。鸵鸟算法的使用前提是,问题出现的概率很低。
死锁的检测和恢复
第二种,这种方式不会尝试阻止去阻止死锁的出现。相反,这种解决方案会希望死锁尽可能的出现,在检测到死锁出现后,对其进行恢复。
(1)每种类型一个资源的死锁检测方式
————死锁的检测就是基于向量的比较。每个进程起初都是没有被标记过的,算法会开始对进程做标记,进程被标记后说明进程被执行了,不会进入死锁,当算法结束时,任何没有被标记过的进程都会被判定为死锁进程。
——
——
——
那么问题来了和时去检测死锁呢?(两个考量标准)
————1、每当有资源请求时就去检测,这种方式会占用昂贵的CPU时间
————2、每隔k分钟检测一次,或者当CPU使用率降低到某个标准下去检测。考虑到CPU效率的原因,如果死锁进程达到一定的数量,就没有多少进程可以运行,所以CPU会经常空闲。
——
——
——
我们的最终目的是让程序正常的运行下去,所以检测出来死锁是要对其恢复的,下面我们就讨论几种死锁的恢复方式:
(1)通过抢占进行恢复
某些情况下,可能会临时将某个资源从它的持有者转移到另一个进程。比如在不通知原进程的情况下,将某个资源从进程中强制取走给其他进程使用,使用完之后在送回来。这种方式困难,简单粗暴,并不可取。
(2)通过回滚进行恢复
如果系统设计者和机器操作员知道可能发生死锁,从而定期检查流程。进程的检测点意味着进程的状态可以被写入到文件以方便后面进行恢复。检测点不仅包含储存映像,还包含资源状态。一种更有效的解决方式是不要覆盖原有的检测点,而是没出现一个检测点都要把它写入到文件中,这样进程执行时,就会有一系列的检查点文件被积累起来。
——为了进行恢复,要从上一个较早的检查点上开始,这样所需要资源的进程会回滚到上一个时间点,在这个时间点上,死锁进程还没有获取所需要的资源,可以在此时对其进行资源分配。
(3)杀死 进程恢复
最简单有效的解决方案是直接杀死一个死锁进程。但是杀死一个进程可能照样行不通,这时候就需要杀死别的资源进行恢复。另外一种方式是选择一个环外的进程做为牺牲品来释放进程资源。
死锁避免
我们来探讨几种规避死锁的方式。
(1)单个资源的银行家算法
是一种死锁的调度算法,模型是基于一个城镇中的银行家,银行家想城镇中的客户承诺了一定数量的贷款额度。算法要做的就是判断请求是否会进入一种不安全的状态。如果是,就拒绝请求,如果请求后系统是安全的,就接受该请求。
破坏死锁
死锁本质上是无法避免的,因为它需要获得未知的资源和请求,但死锁是满足四个条件后才出现的,他们分别是:互斥、保持和等待、不可抢占、循环等待
——
我们接下来对着四个条件进行讨论,只要破坏其中一个,就能够破坏死锁。
(1)破坏互斥条件
这是我们首先考虑的。如果资源不被一个进程独占,那么死锁就不会产生。例如打印机同时使用一个资源会造成混乱,解决方法是使用假脱机打印机,这项技术可以允许多个进程同时产生输出,这种模型中,实际请求打印机的唯一进程是打印机守护进程也成为后台进程。后台进程不会请求其他资源,这样就可以消除打印机的死锁。
后台进程通常被编写为能够输出完整的文件后才能打印,假如两个进程都占用了假脱机空间的一半,而这两个进程都没有完成全部的输出,就会导致死锁。因此,尽量做到尽可能少的进程可以请求资源。
——
——
(2)破坏保持等待的条件
如果我们能阻止持有资源的进程请求其他资源,我们就能够消除死锁。一种实现方式是让所有的进程开始执行前请求全部的资源。如果所需的资源可用,进程会完成资源的分配并运行到结束。如果有任何一个资源处于频繁分配的情况,那么没有分配到资源的进程就会等待。
很多进程无法在执行完成前就知道到底需要多少资源,如果知道的话,就可以使用银行家算法;还有一个问题是这样无法合理有效利用资源。
还有一种方式是进程在请求其他资源时,先释放所占用的资源,然后再尝试一次获取全部的资源。
——
——
(3)破坏不可抢占条件
通过虚拟化的方式来避免这种条件。
——
——
(4)破坏循环等待条件
循环等待条件可以通过多种方法来破坏。一种方式是制定一个标准,一个进程在任何时候只能使用一种资源。如果需要另外一种资源,必须释放当前资源。对于需要将大文件从磁带复制到打印机的过程,此限制是不可接受的。
另一种方式是将所有的资源统一编号,进程可以在任何时间提出请求,但是所有的请求都必须按照资源的顺序提出。如果按照此分配规则的话,那么资源分配之间不会出现环。尽管通过这种方式来消除死锁,但是编号的顺序不可能让每个进程都会接受。