文章目录
- 一. 什么是死锁
- 二. 死锁产生的四个条件
- 三. 避免死锁
- 1. 死锁检测算法
- 2. 银行家算法
- 结束语
一. 什么是死锁
- 死锁是指一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所占用的不会释放的资源,而处于一种永久等待的状态。
就像下图(图片来自网络)
第一种死锁是,线程A和线程B同时让线程C让路,但因为空间狭窄,并且两人都互补想让,所以一直处于等待状态
第二种死锁是,线程A和线程B互相阻塞,都抢夺路权,并且不相让自己的,所以处于等待状态
二. 死锁产生的四个条件
死锁产生的四个条件属于必要条件,即如果出现死锁,必然由这四种条件导致,不过反之,可能还出现第5,第6种情况,也导致死锁。
- 互斥条件: 一个资源每次只能被一个执行流使用
- 请求与保持条件: 一个执行流因请求资源而阻塞时,对已获得的资源保持不释放
- 循环等待条件: 若干个执行流之间形成的一种头尾相接的循环等待资源的关系
- 不剥夺条件:一个执行流已获得的资源,在未使用完之前,不能被强行剥夺
三. 避免死锁
避免死锁的一种方法就是破坏上述的四个条件,只要破坏其中的任意一个
,就不会产生死锁。
- 对于互斥条件:我们可以尽量减少对临界资源的访问,减少加锁解锁的操作
- 对于请求与保持条件:pthread_mutex_trylock函数,在多次加锁后,如果仍不成功,会解除自己所申请的锁。
- 循环等待条件:使得加锁的顺序一致,比如两个线程都获取A,B两把锁。两个线程获取的顺序都是AB,减少交错的情况。如果一个线程AB,一个线程BA,那么一定会死锁。
- 不剥夺条件:解锁操作允许其他线程进行,即可以剥夺资源。
还有一些其他方法:
- 避免锁未释放的场景
- 资源一次性分配
有两种常见的避免死锁的方法:
死锁检测算法
银行家算法
1. 死锁检测算法
死锁检测算法,首先需要一种数据结构来保存资源的请求和分配
其次是通过算法,利用请求和分配信息检测系统是否存在死锁
首先画图理解一下
如果系统中空闲的资源满足线程所需资源数量,那么该线程不会阻塞。
而当一个线程完成执行任务,将资源归还给操作系统,那么空闲的资源变多,可能使得一些本来因空闲资源不足而阻塞等待的线程被激活,开始执行任务。
以此类推,当最后所有线程都完成任务时,表面给程序没有死锁。
当一个线程可以完成任务时,我们可以在图中将其有向边消除。比如P1完成任务。
然后再P2完成任务
所有有向边消除,表面该程序没有死锁。
但如果是以下场景
R1分配2个资源给P1,分配1个资源给P2,R2分配1个资源给P2,但是此时,P2需要两个R1资源才能开始执行任务,P1需要两个R2资源才能执行任务,两个线程互相等待资源,但又不释放自己分配到的资源,导致死锁。
检测死锁的算法
在资源分配图中,找到既不阻塞又不是孤点的线程Pi(即找出一条有向边与它相连,且该有向边对应资源的申请数量小于等于系统中已有空闲资源数量。若所有链接该线程的有向边都满足次条件,那么该线程可以执行任务,然后归还资源。)
然后线程Pi归还的资源可能唤醒其他线程执行任务,当最后所有有向边都消除了,那么该程序没有死锁,反之,剩下的有向边是导致死锁的原因之一。
2. 银行家算法
后续补充
结束语
感谢你的阅读
如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。