【经典结构】死锁
死锁
1.概念
一个很通俗易懂的例子:假设有红蓝两把钥匙开红蓝两个门,两个人分别执行六条指令,最后要能够都把两扇门打开。 注意红蓝钥匙都各只有一把,也就是说两个人共享这对钥匙。
比如下面这幅图的解法:
文章图片
两个人同时执行,A能够顺利把门打开,因为它正好在第3步的时候能拿到B归还后的红钥匙,但是对B就不一样了,因为A没有及时归还蓝钥匙,在最后才想起来还,那B在第四步的时候想要拿到蓝钥匙,需要等A在第6步把蓝钥匙还了才行,也就是得等着A完事以后B才能完事,所以两个人完成时间并不相同(也就是两个线程A先结束,B再结束),但终究还是都完成了。
那再看下面这个解法:
文章图片
两个人A和B在第三步的时候,A想要获取红钥匙,等着B归还红钥匙;B想要获取蓝钥匙,等着A归还蓝钥匙,那这两个人永远在这卡着,进行不下去了,这就是死锁。
问:什么是死锁?
死锁就是多个线程在运行的时候互相抢夺资源,造成了一种僵持的阻塞状态。比如线程AB分别握着锁a和锁b,但是这时候两个线程又都想获得对方的锁,又谁都不松手,这时候就形成了僵局,成了阻塞状态。
2.条件
上面想开两扇门其实有很多种解法,那什么时候会出现死锁,比如同样的问题解法1就不会死锁,解法2就会死锁。一般来说,死锁有四个必要条件:
问:死锁产生的条件?
- 互斥条件:某资源某一时刻只能被一个线程占用。--只有一对钥匙;
- 请求与保持条件:当一个线程请求新的资源而阻塞后,对已经获得的资源保持不放。 --A拿着红钥匙又想要蓝钥匙,还不归还红钥匙;
- 不剥夺条件:一个线程拿到资源后不能被剥夺,只能由自己释放。 --人除非自己主动归还钥匙,不然就一直占着;
- 环路等待条件:在发生死锁时,必然存在着线程之间头尾相连循环等待资源的关系;比如线程P0等待着P1的资源,P1等待着P2的资源,...,Pn等待着P0的资源。 --拿着红钥匙的A在等蓝钥匙,拿着蓝钥匙的B在等红钥匙;
问:如何避免死锁?
- 破坏互斥条件:这个条件没办法进行破坏,因为我们用锁的目的就是想让它们互斥。
- 破坏请求与保持条件:只要有一个资源得不到分配,那也不给这个线程分配其他资源。 --一个人拿到一把钥匙后,只有还了才能去请求下一把;
- 破坏不剥夺条件:当某线程拿着资源,但是得不到其他资源,那就释放自己的资源。 --比如可以设置A拿着钥匙等了十分钟还是执行不了下一步,那就自动归还自己的钥匙;
- 破坏环路等待条件:每类资源都申请一个编号,每个线程按顺序申请资源,按相反顺序释放资源。 --上面产生死锁一定是A和B都先拿了不同的钥匙,比如可以规定任何线程都只能先拿红钥匙再拿蓝钥匙。
- 银行家算法;
- 顺序加锁:确保线程按照相同的顺序获得锁(上面提到的4);
- 限时加锁:线程在尝试获取锁的时候加一个超时时间,超过这个时间就放弃该请求,并把自己获得的锁释放(上面提到的3);
四种结构
- 最大需求资源数量Max(例如Max[j]=4,表示当前进程i对资源j的最大需求量为4);
- 已分配给进程的资源Allocation(例如Allocation[j]=4,表示当前进程i已经分配的资源j数量为4);
- 还需要的资源数量Need(例如Need[j]=4,表示当前进程i还需要资源j的数量为4);Need[j]=Max[j]-Allocation[j]
- 空闲资源数量Available(例如Available[j]=4,表示当前资源j的空闲数量为4);
- 1.假设进程P1申请资源,银行家算法先试探性的分配给他(当然先看看当前资源池中的资源数量够不够)
- if申请的资源数量<=Available(操作系统(银行家))所有的资源,那就执行2;
- if申请的资源数量>Available-->不安全;
- 2.判断分配给P1后剩余的资源,能不能使进程队列中的某个进程执行完毕;
- if有进程可执行完毕,那就执行3;
- if没有进程可执行完毕,那系统处于不安全状态(即此时没有一个进程能够完成并释放资源,随时间推移,系统终将处于死锁);
- 3.经过2判断后有进程可执行完毕,则假设回收已经分配给它的资源(剩余资源数量增加),并把这个进程标记为可完成,然后接着判断队列中的其他进程;
- 4.如果所有进程都可执行完毕,那系统就处于安全状态,并根据刚才的顺序生成安全序列(例如{P0,P3,P2,P1}表示将申请后的资源work先分配给P0->回收P0(原work+进程P0已分配的Allocation=新work)->分配给P3->回收P3->...
- 安全状态:如果存在一个由系统中所有进程构成的安全序列,那系统安全状态,安全状态一定没有死锁;
- 不安全状态:不存在一个安全序列。不安全状态不一定死锁;
比如当前出现下述资源分配:
文章图片
上文一共有4种资源,例如P0 1号资源已经分配的为0;3号资源分配的为3;
问:该状态是否安全?
根据上面的过程可以列出下面的表:
文章图片
work指的是资源池里可以利用的资源,根据上面的Available,发现其能满足P0的need,然后求出回收P0的新work,接着发现能满足P3,...,就这样不断进行;最后能找到一个序列{P0,P3,P4,P1,P2},所以系统是安全的。
问:if 进程P2提出请求Request(1,1,2,2),系统能分配给它吗?
检查步骤:
- 1.Request2(1,1,2,2)<=Need2(2,3,4,5)
- 2.Request2(1,2,2,2)<=Available(1,6,2,2)
- 3.两者都满足,那就先假设为P2分配资源,然后修改Available,Allocation,Need2;
Available(0,4,0,0)
Allocation2(2,5,7,6)
Need2(1,1,3,4) - 4.这时候再进行检查,Available(0,4,0,0) 谁也满足不了了,系统进入不安全状态,所以不能分配给P2资源。
银行家算法
推荐阅读
- 宽容谁
- 我要做大厨
- 增长黑客的海盗法则
- 画画吗()
- 2019-02-13——今天谈梦想()
- 远去的风筝
- 三十年后的广场舞大爷
- 叙述作文
- 20190302|20190302 复盘翻盘
- 学无止境,人生还很长