死锁

为了线程安全,我们在需要的是会使用”独占锁“,但过多的锁定也会有麻烦。多个线程因为竞争资源相互等待而造成的僵局,我们称为死锁。若无外力作用,这些进程将都无法推进。在死锁中,至少有两个线程被挂起,并等待对方解除锁定。

我们先看一个小例子:在一个平面上有很多方块,有一些星星在这上面移动。基本规则就是:每个方块只能有一个星星。

(图1)

移动过程如下图,小黑想从a2方块移动到a3方块。这时小黑得占用a2位置,当a3位置为空时跳过去。

(图2)

当想移动的目标位置被其他星星占着的时候,就等其他星星移走后再移动过去。如下图小绿,会等到小黑移走后再移动到a2。

(图3)

但当小黑想移动的目标位置是b2的时候就悲剧了,固执的星星小黑和小绿将相互等待对方移走,直到永远。

(图4)

可能会出现更复杂的情况,小黑在等待小红移走,小红在等待小蓝移走,小蓝在等待小绿移走,小绿在等待小黑移走。这样僵持着!

(图5)

或更更复杂的情况(脑补)。。。

产生死锁的条件

产生死锁必须同时满足以下四个条件,只要其中任一条件不成立,死锁就不会发生。

  • 互斥条件:进程要求对所分配的资源进行排他性控制,即在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。对应我们例子就是,每个方块只能容的下一个星星。
  • 不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放(只能是主动释放)。对应我们的例子就是,星星只能等待目标位置星星自己走,而不能把它推下方块。
  • 请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。对应我们的例子就是,星星得占着一个方块,然后找目标方块。
  • 循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被链中下一个进程所请求。

预防死锁

从我们的例子出发,我们能想到的方法有:
1. 让星星只能按顺序跳,例如规定的顺序是a0...an...b1...bn...c1...cn。当然,有能力的星星可以跨越着跳,例如从a0到c1,但不能违背顺序逆着来。当到想回头的时候,就必须先下了方块(释放锁)再从头开始。
2. 当星星想移动的目标位置被其他星星占着的时候,就等其他星星移走后再移动过去。这是星星的移动规则,我们可以在这里加个时限,当等待的时间超过时限,就运行星星“休息”,星星就先下方块(释放锁),休息一段时间后再继续。
3. 如果星星的移动线路是比较简单的,例如每次启动只移动5步,则可以采用预定的方法。星星开始移动的时候就锁定所有将移动的方块。
4. 改变星星的基本移动方法,例如从a0->a1,移动过程改成,先下方块a0(释放资源),然后再到a1上。
5. 在4的基础上改进,每次都要下方块比较不方便,所以我们改成,当需要等待移动目标方块上星星移走的时候再先下方块。 
6. 找个管理者,当发现锁死的时候,把这些固执的星星都叫下方块。让每个星星随机等一段时间再继续。
第1种方案:按照顺序加锁是一种有效的死锁预防机制。但是,这种方式需要你事先知道所有可能会用到的锁,但总有些时候是无法预知的。基本思想就是破坏产生死锁的必要条件——循环等待条件。
第2种方案:是在尝试获取锁的时候加一个超时时间,这也就意味着在尝试获取锁的过程中若超过了这个时限该线程则放弃对该锁请求。若一个线程没有在给定的时限内成功获得所有需要的锁,则会进行回退并释放所有已经获得的锁,然后等待一段随机的时间再重试。这段随机的等待时间让其它线程有机会尝试获取相同的这些锁,并且让该线程在没有获得锁的时候可以继续运行(加锁超时后可以先继续运行干点其它事情,再回头来重复之前加锁的逻辑)。这算是一种预防,没破坏死锁的必要条件。且,如果多个线程同时请求几个资源的时候,因为等待的时间有一样,容易出现重复尝试,始终得不到锁。

第3种方案:这种方案比较暴力,杜绝了死锁。但如果一个线程需要很多资源的时候,很浪费。且容易出现,因为所需的某一两种资源不能满足而不给分配资源。

第4、5种方案:这种方案破坏产生死锁的必要条件——请求和保持条件。但并不是什么情况下都能这么用。

第6种方案:这个就是死锁检测,当发现死锁的时候进行处理。

一个可行的做法是释放所有锁,回退,并且等待一段随机的时间后重试。这个和简单的加锁超时类似,不一样的是只有死锁已经发生了才回退,而不会是因为加锁的请求超时了。虽然有回退和等待,但是如果有大量的线程竞争同一批锁,它们还是会重复地死锁。

一个更好的方案是给这些线程设置优先级,让一个(或几个)线程回退,剩下的线程就像没发生死锁一样继续保持着它们需要的锁。如果赋予这些线程的优先级是固定不变的,同一批线程总是会拥有更高的优先级。为避免这个问题,可以在死锁发生的时候设置随机的优先级。

C# 多线程系列(五)的更多相关文章

  1. java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析

    java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java ...

  2. java多线程系列五、并发容器

    一.ConcurrentHashMap 1.为什么要使用ConcurrentHashMap 在多线程环境下,使用HashMap进行put操作会引起死循环,导致CPU利用率接近100%,HashMap在 ...

  3. Java多线程系列五——列表类

    参考资料: http://xxgblog.com/2016/04/02/traverse-list-thread-safe/ 一些列表类及其特性  类 线程安全 Iterator 特性 说明 Vect ...

  4. 【Java多线程系列五】列表类

    一些列表类及其特性  类 线程安全 Iterator 特性 说明 Vector 是 fail-fast 内部方法用synchronized修饰,因此执行效率较低 1. 线程安全的列表类并不意味着调用它 ...

  5. (Java多线程系列五)守护线程

    守护线程 什么是守护线程 Java中有两种线程,一种是用户线程,一种是守护线程. 当进程不存在或主线程停止,守护线程也会自动停止. class DaemonThread extends Thread ...

  6. Java多线程系列目录(共43篇)

    最近,在研究Java多线程的内容目录,将其内容逐步整理并发布. (一) 基础篇 01. Java多线程系列--“基础篇”01之 基本概念 02. Java多线程系列--“基础篇”02之 常用的实现多线 ...

  7. java多线程系列(一)

    java多线程技能 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...

  8. java多线程系列(二)

    对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...

  9. java多线程系列(三)---等待通知机制

    等待通知机制 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解 ...

  10. java多线程系列(四)---Lock的使用

    Lock的使用 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理 ...

随机推荐

  1. noip模拟赛 立方数

    题目描述LYK定义了一个数叫“立方数”,若一个数可以被写作是一个正整数的3次方,则这个数就是立方数,例如1,8,27就是最小的3个立方数.现在给定一个数P,LYK想要知道这个数是不是立方数.当然你有可 ...

  2. hdu 1533KM算法

    #include<stdio.h> #include<string.h> #include<math.h> #define inf 0x3fffffff #defi ...

  3. 一位ACMer过来人的心得

    http://blog.csdn.net/acm_cxlove/article/details/8079348

  4. 逆序对&求逆序对

    题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定 ...

  5. spring boot jpa 事务管理

    spring boot 对jpa的支持极为方便,基本上不需要作太多配置,只需要加上注解就能支持事务: @Controller @Transactional(rollbackOn = Exception ...

  6. android在listview中放入从sdcard读取的bitmap

    重写viewbinder public class viewbinder_bookmark implements SimpleAdapter.ViewBinder{ @Override public ...

  7. [bzoj1084][SCOI2005]最大子矩阵(DP)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1084 分析: m=1时:相当于只有一行数,让你取出p段,使得总和最大 明显可以DP,f ...

  8. ssh远程连接出现someone counld be eavesdropping on you right now 的错误

    master主机通过ssh远程连接slaves机子时出现下述错误 解决的方法: 一.删除/root/.ssh/下的kown_hosts文件 二.在master机子上又一次运行scp id_dsa.pu ...

  9. 国际维修联合会IMA年度大会在瑞士圆满结束

    瑞士卢加诺 ☆2016年4月5日至7日 中国设备管理协会国际交流合作中心主任.学府咨询(国际)集团董事长.IMA中国分会主席李葆文教授,应邀出席了4月5日至7日在瑞士卢加诺召开的国际维修联合会年度大会 ...

  10. Socket 长连接 短连接 心跳 JAVA SOCKET编程

    简单解释就是: 短连接:建立连接,发送数据包.关闭连接 长连接:建立连接.发送数据包,发送心跳包,发送数据包,发送心跳包.发送心跳包. ..... 所以又频繁的数据收发的话.短连接会频繁创建TCP连接 ...