为了有效预防死锁,最根本的策略是确保死锁的四个必要条件中至少有一个无法成立。那么,这些条件是否可以被破坏?下面逐一进行详细分析。
破坏互斥条件
破坏互斥条件,通俗来说就是允许若干进程同时共享同一资源。但现实情况是,许多资源天生具有互斥访问的特性,这是它们的固有属性,难以改变。因此,试图通过破坏互斥条件来防止死锁,在绝大多数场景下并不现实。举例来说,打印机是典型的互斥资源——若多个进程并发打印,每个进程只输出一行数据,最终打印出的内容混杂无序,用户显然无法接受这种结果。
破坏占有和等待条件
破坏这一条件,常用的方法是采用资源静态分配策略。具体而言,在进程启动之前,一次性将其所需的全部资源分配到位。如果系统资源充足,则全部给予;如果其中任何一种资源无法满足,则其他资源也不予分配,让进程不持有任何资源。这样一来,进程在运行期间不会再发起新的资源请求,等待条件自然被破坏;同时,进程在等待期间不占用任何资源,也打破了占有条件,从而有效避免死锁的发生。
这种方法的优势在于控制逻辑简单、易于实现。但其缺点也非常明显:进程在运行前就占用了所有资源,即使某些资源只使用很短的时间,也必须一直持有,导致资源利用率大幅降低,并且那些无法一次性获得全部资源的进程会迟迟无法启动运行。
破坏不剥夺条件
破坏这一条件,可以采用剥夺式控制方法。基本思路是:当一个进程已经持有某些资源,但请求新资源时无法满足,它必须暂时释放自己已持有的所有资源(即被剥夺),然后进入等待状态,之后再连同新资源一起重新申请。这样也能有效防止死锁。
但这种方法实现起来相当复杂。进程释放资源时需要保存现场,后续还要恢复,代价较高。而且,这种方法主要适用于处理机与存储器资源,对于其他类型的资源,基本不适用。
破坏循环等待条件
破坏循环等待条件,通常采用资源顺序分配法。核心思想是:将系统内的所有资源按层次进行分级。一个进程一旦获得某一层的某个资源,就只能进一步申请更高层的资源;如果要释放某一层的资源,则必须先释放更高层的资源;如果进程想申请同一层中的另一个资源,就必须先释放当前在该层已占有的资源。也就是说,释放资源的顺序与申请资源的顺序正好相反。这样,循环等待现象就不会出现,死锁自然得以避免。
使用这种方法时,关键在于如何合理安排资源的层次顺序。通常的做法是:将各进程频繁使用、较为通用的资源放在较低层次,而将重要且稀有的资源放在较高层次,以最大限度地提升资源利用率。与前面几种方法相比,资源顺序分配法在资源利用率和系统吞吐量方面均有明显改善,但也存在一些缺陷:
(1)低层次资源必须在进程请求高层次资源之前提前申请,如果这些资源暂时用不上,就会处于空闲等待状态,造成浪费。
(2)资源层次一经设定,便不能轻易更改,这限制了新类型设备的加入。
(3)层次顺序通常依据大多数进程的使用习惯来设定。对于资源使用顺序恰好匹配的进程,效率很高;但对于不匹配的进程,资源浪费依然存在。
