计算机系统011 - 操作系统之死锁
上一篇 计算机系统010 - 操作系统之并行 中讲述了并行中的多进程/线程对同一资源的竞争会引发冲突,导致程序执行结果不可预测。通过使用信号量、管程、消息传递等机制,可实现进程间的同步和通信,达成互斥基础上的合作。但事实上,进程运行过程中可能同时会同时使用多个资源,假如两个进程在 占用对方所需资源的同时,去获取对方占有资源 ,就会形成死锁。
为便于书写,后续多进程/线程统一视为多线程,毕竟进程本身至少也是以一个主线程的形式执行的。
从前面简短的描述来看,死锁现象中至少需要如下参与者:
死锁有三个必要条件:
这三个条件都只是死锁存在的必要条件,但不是充分条件。死锁的真正产生还需要第四个条件:
光从理论上来讲难免过于空洞,既然说到了死锁,那就不得不说起一个经典问题:哲学家就餐。
有五位哲学家住在一栋房子里,在他们面前有一张餐桌,每位哲学家的生活就是思考和吃饭。通过多年的思考,所有的哲学家一致同意最有助于他们思考的食物是意大利面条。但由于动手能力有限,每位哲学家需要两把叉子来吃面条。
现在的问题是需要设计一套礼仪(算法)以允许哲学家就餐,算法必须保证互斥(没有两位哲学家同时使用同一把叉子),同时还要避免 死锁和饥饿 。所谓饥饿,就是指长时间得不到资源的使用权而无法完成任务,只能阻塞住白白浪费生命。
对此,通常有如下几种解法:
上述的是通用的解法,虽然解法能解决问题,但授人以鱼不如授人以渔,解法中遵循的原理还需要进一步说明。
死锁预防,就是排除发生死锁的可能性,即破坏4个条件之一来避免死锁的产生。预防方法可以进一步分为两种:
从上面我们可以看到, 死锁预防主要是从资源使用权本身着手 ,破坏四个条件之一来防止死锁的形成,但由于引入了资源等待,拉长了任务所需执行时长,造成低效后果。
为了避免因为预防死锁而导致所有线程变慢,死锁避免采用了与死锁预防相反的措施。它允许三个必要条件,但通过算法 判断资源请求是否可能导致循环等待的形成并相应决策 ,来避免死锁点的产生。因此,其前提是知道当前资源使用的整体情况,以及申请资源线程本身所占有的资源细节。
判断和决策中,主要使用两种避免方法。
整体来看, 死锁避免是从资源和线程相互间关系着手,避免形成循环等待是其主要任务。
相比前面两种方法的保守,死锁检测就要自信而奔放得多。死锁检测中,尽可能将被请求的资源分配给线程,操作系统会周期性执行算法检测是否有循环等待的产生。换句话说,就是放手去干,操作系统罩着你们。
当然,检查算法执行的频率影响着死锁被检测出的灵敏度,操作系统可以在每次资源请求是检测,也可以适当降低频率,减少消耗的CPU时间。检测到死锁后,就需要解决死锁。目前操作系统中主要采用如下几种方法:
既然三种方法各有优劣,那就不如海纳百川,取其精华去其糟粕。
翻译一下,就是说先根据资源特性分类(至于为什么要分类,前面也提过,分类是为了更细粒度的控制),类和类之间可以通过排优先级来约束,而类本身内部,再通过合适算法来选择。
说起资源,顺便多提一下。操作系统中资源通常分为如下两种:
本篇主要介绍了死锁的形成条件、相应的解决方法及各解决方法优劣之处,相比其他篇内容,本篇略显单薄了一些,不过还是希望对于一些概念的理解能够引发共鸣,留下印象。最近两篇中讲述的是操作系统并行、死锁两个调度相关的问题,接下来就要从内存管理部分对进程调度做进一步展开。
2024-10-28 广告