您的位置:首页 > 其它

关于多线程死锁的小记

2018-03-26 23:06 162 查看
1、造成多线程死锁的原因:
    a、系统中的资源数量不够进程使用,而造成的资源竞争。例如进程P1、P2同时共享了打印机和磁盘机,P1被分配了打印机,P2被分配了磁盘机,但同时P1请求磁盘机,P2请求打印机。就会造成P1、P2互相等待,形成死锁。
    b、加锁顺序不当(这点理解的不是很透彻,总觉得加锁顺序不当只是资源数量不足中的一种情况,因为假设资源无限多,即使顺序不当,也不至于产生死锁。。。)

A、B两个人,要用一双筷子吃饭。A拿了左边的筷子,B拿了右边的筷子。两个人都拿着自己的一支筷子不放下,又都等待对方的筷子,就造成两人都吃不了饭。
2、死锁的4个必要条件:
    a、互斥条件:你有我就不能有,我有你就不能有。
    b、不可剥夺条件:我的东西你不能硬抢,只有我自己不要了。
    c、请求和保持条件:吃着碗里看着锅里,有了一个还想有一个。自己那个还不肯放手。
     d、循环等待条件:你想要的正好我有,我想要的正好你有。

3、循环等待是造成死锁的必要条件,而不是充分条件。也就是说,循环等待不一定就死锁了,但死锁了就一定是循环等待了。
A=>B=>C=>A||=>D。A等待B,B等待C,C等待A或者D。此时如果A、D都持有资源不释放,就已经循环等待了。但是D是循环体外的元素,如果D释放资源,就可以解开这一次的死锁。
自己懒的画图,下图截自:https://blog.csdn.net/ls5718/article/details/51896159



如何避免死锁呢?
1、顺序加锁(该方案只是预防机制,而且要整理所有用到锁的顺序,万一漏了就GG了,而且有些场景根本无法做到顺序加锁)
    线程T1、T2,共享资源S1、S2。T1的加锁顺序是S1=>S2,T2的加锁顺序是S2=>S1。那么执行完第一步时,T1持有S1,T2持有S2。第二步T1请求S2,但S2已经被T2持有;T2请求S1,但是S1已经被T1持有。T1、T2就会互相等待对方手中的资源,造成死锁。
   如果加锁顺序都是S1=>S2的话,假设T1先持有S1,此时T2请求S1,但S1已被T1持有,T2必须等到T1释放S1后才能继续下一步。T1释放S1后,请求S2,可以获得S2的持有权,同时T2获得S1的持有权。
2、加锁倒计时
    如果线程在指定时间内没有获得所有需要的锁,就会主动释放所有拥有的锁,并在随机一段时间后,继续重新请求。(鸵鸟行为,因为下一次重新请求还是有可能触发死锁,并且运行的线程越多的话,概率越高)

3、死锁检测机制
    在检测到死锁发生的情况后,进行回退操作,即释放线程所有持有的锁。(无语,因为下一次依旧有概率会发生死锁)该方案可以稍微改动一下:再检测到死锁发生时,给线程随机设置优先级,优先级低的锁释放自己持有的资源,那么优先级高的线程就有可能获得等待的资源,从而解开死锁。

???有没有一个彻底解决死锁的方案?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: