死锁
四个必要条件
(1)互斥条件:进程对所分配到的资源不允许其他进程访问,若其他进程访问,只能等待,直到进程使用完成后释放该资源;
(2)请求保持条件:进程获得一定资源后,又对其他资源发出请求,但该资源被其他进程占有,此时请求阻塞,而且该进程不会释放自己已经占有的资源;
(3)不可剥夺条件:进程已获得的资源,只能自己释放,不可剥夺;
(4)环路等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
如何解决死锁?
死锁的四个必要条件中,无法破坏的是 互斥条件
互斥地使用资源是多进程能正确工作的前提,是必须保证满足的,不能破坏,否则就会出现问题如读写不一致。
因此我们着眼破坏剩下的三个条件。
1、破坏请求保持条件
资源一次性分配。进程在运行前一次申请完它所需要的全部资源,在它的资源末满足前,不让它投入运行。一旦投入运行后,这些资源就一直归它所有,该进程就不会再请求别的任何资源了。
实现简单但有明显的缺点。有些资源可能只需要用很短的时间,因此如果进程的整个运行期间都一直保持着所有资源,就会造成严重的资源浪费,资源利用率极低。另外,该策略也有可能导致某些进程饥饿。
什么是进程饥饿?
人不吃饭会饥饿,对进程来说,他要吃的饭就是资源(计算资源,磁盘IO,打印机等等),超过一段时间没有吃到饭就会饥饿。
有时资源分配策略可能是不公平的,即不能保证等待时间上界的存在(就是不能保证在某个时间节点之前给你答复)。在这种情况下,即使系统没有发生死锁,某些进程也可能会长时间等待.当等待时间给进程推进和响应带来明显影响时,称发生了进程饥饿,当饥饿到一定程度的进程所赋予的任务即使完成也不再具有实际意义时称该进程被饿死。
2、破坏不可剥夺条件
当进程新的资源未得到满足时,释放已有的资源
两种实现方案:
- 方案一:
当某个进程请求新的资源得不到满足时,它必须立即释放保持的所有资源,待以后需要时再重新申请。也就是说,即使某些资源尚未使用完,也需要主动释放,从而破坏了不可剥夺条件。 - 方案二:
当某个进程需要的资源被其他进程所占有的时候,可以由操作系统协助,将想要的资源强行剥夺。这种方式一般需要考虑各进程的优先级(比如:剥夺调度方式,就是将处理机资源强行剥夺给优先级更高的进程使用)
缺点:
- 实现起来比较复杂
- 释放己获得的资源可能造成前一阶段工作的失效。因此这种方法一般只适用于易保存和恢复状态的资源,如CPU
- 反复地申请和释放资源会增加系统开销,降低系统吞吐量
- 若采用方案一,意味着只要暂时得不到某个资源,之前获得的那些资源就都需要放弃,以后再重新申请。如果一直发生这样的情况,就会导致进程饥饿
3、破坏环路等待条件
可采用顺序资源分配法。首先给系统中的资源编号,规定每个进程必须按编号递增的顺序请求资源(释放则相反),同类资源(即编号相同的资源)一次申请完。
为什么可行?
一个进程只有已占有小编号的资源时,才有资格申请更大编号的资源。按此规则,己持有大编号资源的进程不可能逆向地回来申请小编号的资源,从而就不会产生循坏等待的现象。
其实上面这句解释还是不好理解。用反证法思考,考虑环路等待,两个进程相互想请求对方持有的资源,这两个资源是有编号的,所以一定有一个大小关系,再根据上面的规则,持有大编号资源的进程一定已经拥有了小编号资源,所以不存在这种环路。
缺点:
- 不方便增加新的设备,因为可能需要重新分配所有的编号
- 进程实际使用资源的顺序可能和编号递增顺序不一致,会导致资源浪费(就是拿到手的资源不一定是立即使用的,极端情况就是最后拿到的资源最先使用,最先拿到的资源最后使用,浪费至极)
- 必须按规定次序申请资源,用户编程麻烦
参考:
2.4.2 死锁的处理策略-预防死锁(破坏互斥条件、破坏不可剥夺条件、破坏请求和保持条件、破坏循环等待条件)_2021、小林子的博客-CSDN博客