预计阅读本页时间:-
6.2.2 死锁建模
Holt(1972)指出如何用有向图建立上述四个条件的模型。在有向图中有两类节点:用圆形表示的进程,用方形表示的资源。从资源节点到进程节点的有向边代表该资源已被请求、授权并被进程占用。在图6-3a中,当前资源R正被进程A占用。
由进程节点到资源节点的有向边表明当前进程正在请求该资源,并且该进程已被阻塞,处于等待该资源的状态。在图6-3b中,进程B正等待着资源S。图6-3c说明进入了死锁状态:进程C等待着资源T,资源T被进程D占用着,进程D又等待着由进程C占用着的资源U。这样两个进程都得等待下去。图中的环表示与这些进程和资源有关的死锁。在本例中,环是C-T-D-U-C。

我们再看看使用资源分配图的方法。假设有三个进程(A,B,C)及三个资源(R,S,T)。三个进程对资源的请求和释放如图6-4a~图6-4c所示。操作系统可以随时选择任一非阻塞进程运行,所以它可选择A运行一直到A完成其所有工作,接着运行B,最后运行C。
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

上述的执行次序不会引起死锁(因为没有资源的竞争),但程序也没有任何并行性。进程在执行过程中,不仅要请求和释放资源,还要做计算或者输入/输出工作。如果进程是串行运行,不会出现当一个进程等待I/O时让另一个进程占用CPU进行计算的情形。因此,严格的串行操作有可能不是最优的。不过,如果所有的进程都不执行I/O操作,那么最短作业优先调度会比轮转调度优越,所以在这种情况下,串行运行有可能是最优的。
如果假设进程操作包含I/O和计算,那么轮转法是一种合适的调度算法。对资源请求的次序可能会如图6-4d所示。假如按这个次序执行,图6-4e~图6-4j是相应的资源分配图。在出现请求4后,如图6-4h所示,进程A被阻塞等待S,后续两步中的B和C也会被阻塞,结果如图6-4j所示,产生环路并导致死锁。
不过正如前面所讨论的,并没有规定操作系统要按照某一特定的次序来运行这些进程。特别地,对于一个有可能引起死锁的资源请求,操作系统可以干脆不批准请求,并把该进程挂起(即不参与调度)一直到处于安全状态为止。在图6-4中,假设操作系统知道有引起死锁的可能,那么它可以不把资源S分配给B,这样B被挂起。假如只运行进程A和C,那么资源请求和释放的过程会如图6-4k所示,而不是如图6-4d所示。这一过程的资源分配图在图6-4l~图6-4q中给出,其中没有死锁产生。
在第q步执行完后,就可以把资源S分配给B了,因为A已经完成,而且C获得了它所需要的所有资源。尽管B会因为请求T而等待,但是不会引起死锁,B只需要等待C结束。
在本章后面我们将考察一个具体的算法,用以做出不会引起死锁的资源分配决策。在这里需要说明的是,资源分配图可以用作一种分析工具,考察对一给定的请求/释放的序列是否会引起死锁。只需要按照请求和释放的次序一步步进行,每一步之后都检查图中是否包括了环路。如果有环路,那么就有死锁;反之,则没有死锁。在我们的例子中,虽然只和同一类资源有关,而且只包含一个实例,但是上面的原理完全可以推广到有多种资源并含有若干个实例的情况中去(Holt,1972)。
总而言之,有四种处理死锁的策略:
1)忽略该问题。也许如果你忽略它,它也会忽略你。
2)检测死锁并恢复。让死锁发生,检测它们是否发生,一旦发生死锁,采取行动解决问题。
3)仔细对资源进行分配,动态地避免死锁。
4)通过破坏引起死锁的四个必要条件之一,防止死锁的产生。
下面四节将分别讨论这四种方法。