一,死锁的定义
多进程多线程的并发执行虽然提高了系统资源的利用率和系统的性能,但也带来了新的问题—–僵局。
死锁(Deadlock)是指多个进程(线程)在执行过程中由于资源竞争或相互通信而被阻塞的现象(它们互相挂起等待)。没有外力,他们将无法前进。此时系统处于死锁状态或者系统有死锁。这些总是互相等待的进程称为死锁进程。
举个生活中简单的例子:小明和小红都想买一块橡皮。这块橡皮值一美元,但每个只有五毛钱。小明说:把你的五毛钱给我,我去买块橡皮。小红说:你把你的五毛钱给我,我去买块橡皮。就这样,两个人互相僵持着,谁也不想低头,谁也买不到橡皮擦。
第二,几种常见的死锁
1.线程会自行锁定。
为了保证线程之间的同步和互斥,我们经常需要锁定线程。有时候线程申请锁资源,还没等到释放。当他们再次申请这个锁时,他们最终会等待这个锁的释放。但是这个锁是他们自己持有的,所以他们会一直挂起等待,导致死锁。
2.多线程竞争资源,循环等待。
有两个线程P1和P2。P1首先申请锁定L1,P2申请锁定L2。此时P1某方向申请锁L2,结果是暂停等待P2释放锁L2,而P2只是想申请锁L1。结果,它被挂起以等待P1释放锁L1,这导致了两个线程之间的死锁。
3.进程推进顺序不正确导致死锁。
有三个线程,P1、P2和P3,分别产生数据M1、M2和M3,并分别接收其他线程产生的数据M3、M2和M1。如果线程推进的顺序是正确的,即三个线程都是先产生数据再接收数据,那么就没有问题。但是一旦一个线程先接收数据再产生数据,就会因为一开始没有产生数据而造成三个线程之间的死锁。
更多Linux内核视频教程文档和资料,可从后台私信[内核]免费获取,自行获取。
内核学习网站:
Linux内核源代码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂
三。死锁的原因和必要条件
1.死锁的主要原因:
系统的资源不足。进程(线程)推进的顺序不对。资源的分配不当。
当系统的资源充裕时,每个进程都可以申请到想要的资源,所以死锁的概率很低。不同的调度顺序和线程速度也会导致死锁。
2.死锁的四个必要条件:
互斥条件:进程(线程)申请的资源在一段时间中只能被一个进程(线程)使用。请求与等待条件:进程(线程)已经拥有了一个资源,但是又申请新的资源,拥有的资源保持不变 。不可剥夺条件:在一个进程(线程)没有用完,主动释放资源的时候,不能被抢占。循环等待条件:多个进程(线程)之间存在资源循环链。
3.处理死锁的方法:
预防死锁:破坏死锁产生的四个条件之一,注意,互斥条件不能破坏。避免死锁:合理地分配资源。检查死锁:利用专门的死锁机构检查死锁的发生,然后采取相应的方法。解除死锁:发生死锁的时候,采取合理的方法解决死锁。一般是强行剥夺资源。
4.四个条件怎么破?
打破互斥条件:改造独占性资源为虚拟大资源,但是大部分资源无法改造,因此不建议使用这个方法。打破请求与保持条件:在进程(线程)运行之前,就把需要申请的资源一次性申请到位,满足则运行,不满足就等待,这样就不会造成在占有资源的情况下,还要申请新资源。打破不可剥夺条件:在占有资源并且还想要申请新资源的时候,归还已经占有的资源。打破循环等待条件:实现资源的有序分配,即对所有的设备进行分类编号,只能以升序的方式来申请资源。
例如,对于P1流程,使用资源的顺序是R2的R1和P2流程,使用资源的顺序是R1的R2。如果采用动态分配,可能会导致死锁。我们对设备进行分类和编号,因此P1和P2只能按照R1和R2的顺序申请资源。可以打破循环,避免死锁。
第四,银行家的算法
最著名的避免死锁的方法是银行家算法,它是由DIJKstra E.W .于1968年提出的。
为什么叫银行家算法?这是因为它有点像银行的“贷款”服务。如果一家银行只有有限的资金为客户提供贷款服务,那么为了保证银行能够有足够的资金运作,就应该在贷款前检查客户是否能够在规定的时间内还款。
在研究我们操作系统的资源分配策略时,也会出现类似的问题。如果要把我们系统中有限的资源分配给各个进程,就要事先检查这个进程是否有能力在规定的时限内归还资源。必须保证在限定的时间内可以归还给其他进程使用。
大致实现方法:
当一个进程对资源的最大需求量不超过系统中的资源数量时就可以接纳该进程。进程可以分期请求资源,当请求的总数不能超过最大需求量。当系统现有的资源不能满足进程尚需资源数时,对进程的请求可以推迟分配,但总能使进程在有限的时间里得到资源。当系统现有的资源能满足进程尚需的资源数时,必须测试系统现存的资源能否满足该进程尚需的最大资源数,若能满足则按当前的申请量分配资源,否则也要推迟分配。
银行家:首先,我们需要定义国家和安全国家的概念。系统的状态是当前分配给进程的资源。因此,状态包含两个向量,Resource(系统中每个资源的总量)和Available(未分配给进程的每个资源的总量),以及两个矩阵,Claim(表示进程对资源的需求)和Allocation(表示当前分配给进程的资源)。安全状态意味着至少有一个资源分配序列不会导致死锁。当一个进程请求一组资源时,假设它同意了请求,从而改变了系统的状态,然后确定结果是否仍处于安全状态。如果是,同意这个请求;如果不是,阻塞进程知道系统状态在同意请求后仍然是安全的。
本文来自掩于岁月投稿,不代表舒华文档立场,如若转载,请注明出处:https://www.chinashuhua.cn/24/491618.html