目录
一、什么是死锁
死锁是指两个或多个进程在执行过程中,因为争夺资源或者相互等待而导致的一种僵持状态,如果没有外部干预,它们都无法继续运行。
例如,一个进程 p1占用了显示器,同时又必须使用打印机,而打印机被进程p2占用,p2又必须使用显示器,这样就形成了死锁。 因为p1必须等待p2发布打印机才能够完成工作并发布屏幕,同时p2也必须等待p1发布显示器才能完成工作并发布打印机,形成循环等待的死锁。
二、死锁产生的原因
如果系统中只有一个进程,当然不会产生死锁。如果每个进程仅需求一种系统资源,也不会产生死锁。不过这只是理想状态,在现实中是可遇不可求的。
死锁的必要条件是指在一个系统中,如果要发生死锁,必须同时满足的四个条件 。这四个条件分别是:
- 互斥条件:每个资源要么已经分配给一个进程,要么就是可用的,不能同时被多个进程共享。
- 占有和等待条件:已经得到了某些资源的进程可以再请求新的资源,而不必释放已经占有的资源。
- 不可抢占条件:已经分配给一个进程的资源不能被其他进程强行夺走,只能由占有该资源的进程自愿释放。
- 环路等待条件:存在一个进程等待队列,其中每个进程都在等待下一个进程所占有的资源,形成一个环路。
这些条件是死锁的必要条件,但不一定是充分条件,也就是说即使这些条件都满足了,也不一定会发生死锁,因为可能存在某种调度策略可以避免死锁的发生。如果要预防或解除死锁,就必须破坏至少一个条件。
三、死锁模型
死锁的模型是指对死锁的产生条件和形式的抽象描述。不同的模型对死锁的检测和解决方法有不同的影响。根据对并发系统中请求的限制程度的不同,死锁共有以下几种模型:
1.One-Resource Model
这是最简单的死锁模型,它假设每个事务每次最多发出一个资源请求,也就是说它的等待图的中每个节点的出度最大为1。事务阻塞直到它发出的请求得到响应。因此这种模型的死锁检测就是查找等待图中是否有环存在。
2.AND Model
与One-Resource 不同的是,这种模型假设每个事务可能同时发出多个请求,这个事务阻塞直到它一次发出的多个请求都得到响应。也就是说,它允许等待图的每个节点的出度为 [0, n]。这种模型的死锁检测和One-Resource一样也是确认等待图中是否有环存在,但不同的是,因为允许一个节点的出度大于1,所以一个事务可能同时参与到了多个环中,它要等到所有的环都被破坏才能解除死锁。
3.OR Model
它是在AND Model上进一步放宽条件,也就是说一个事务可能同时发出一个或多个请求,但是只要有一个请求得到响应,事务即可继续推进。因此这种模型的死锁检测又和上面一种不同,在等待图中,一个节点还是允许有 [0, n]个出度,也就是说这个事务可能参与到了多个环中,只有当这个节点的所有出度所在的路径都在环中时,这个事务才进入死锁,只要有一条路径存在终点,那么这个事务就没有被死锁。
4.AND-OR Model
这是AND Model和OR Model的一种组合模型,它允许一个事务发出 [0, n]个请求,这些请求中即包括AND模型请求,也包括OR模型请求。这样死锁检测更加复杂,甚至没有一个熟悉的图论模型与之对应。对这个模型来说,最容易想到的死锁检测方式,就是反复应用OR 模型的死锁检测方式进行死锁检测。因为死锁具有稳定性,虽然AND—OR进入死锁之前的状态检查十分复杂,但是只要它进入死锁,那么它的状态就不会改变。也就是说当它形成死锁后,它的检测结果和OR模型是一样的,即各个出度都处与环中。
5.Unrestricted Model
这种模型是最通用的模型,它不限制事务的资源请求规则,由于十分复杂,在此也不做介绍。
四、死锁的解决方法
死锁的解决方法主要有以下三种:
1.死锁预防
在程序运行之前,通过破坏死锁的必要条件之一,来阻止死锁的发生。例如规定进程按照一定的顺序请求资源,或者限制进程在申请新资源时必须释放已有资源。
死锁的检测方法主要有资源分配图法和时间延迟法。资源分配图法通过构建进程-资源分配图来检测是否存在环路,时间延迟法通过设置超时时间来检测进程是否进入死锁状态。
2.死锁避免
在程序运行时,通过动态地分析资源的分配情况,来避免进入不安全的状态。例如使用银行家算法,根据进程的最大需求和系统的可用资源,判断是否可以安全地分配资源。
3.死锁检测和恢复
在程序运行时,不试图阻止死锁,而是当检测到死锁发生时,采取措施进行恢复。例如使用死锁检测算法,根据进程-资源分配图,判断是否存在环路,如果存在,则说明发生了死锁。然后,可以通过剥夺或终止一些进程,来释放资源,从而解除死锁。
死锁的出现场景主要有操作系统进程调度、数据库事务处理、分布式系统资源分配等。如操作系统中进程对共享资源如内存、磁盘等的竞争可能导致死锁。
五、其他碎知识补充
1.活锁
活锁(livelock),与死锁相似,死锁是行程都在等待对方先释放资源;活锁则是行程彼此释放资源又同时占用对方释放的资源。当此情况持续发生时,尽管资源的状态不断改变,但每个行程都无法获取所需资源,使得事情没有任何进展。
2.饥饿
饥饿(starvation),是指某些进程因为优先级低或者等待条件不满足,而长期得不到所需的资源,无法执行。饥饿可能是由于资源分配不公平或者调度算法不合理造成的。饥饿的解决方法是保证每个进程都能获得一定的服务,例如使用老化技术,让进程的优先级随着等待时间的增加而提高。
3.混乱
混乱,多个进程由于资源竞争和优先级问题而处于混乱状态。
4.无锁
无锁(lock-free),是指一种不使用互斥锁或者信号量等同步机制,而是通过原子操作来实现多线程之间的协作的编程方法。无锁的优点是可以避免死锁、活锁、饥饿等问题,提高并发性能和可扩展性。无锁的缺点是编程难度高,需要考虑更多的细节和边界情况。无锁的常用技术有CAS(比较并交换)、ABA问题和解决方案、无锁数据结构等。
本文详细阐述了死锁的概念、产生的原因、各种死锁模型(如One-ResourceModel、ANDModel等)、死锁的解决方法(预防、避免和检测恢复)以及相关概念如活锁、饥饿和无锁。
1349

被折叠的 条评论
为什么被折叠?



