博客园优秀文章摘选
并发编程
死锁的产生、排查与解决方案
本文档使用 MrDoc 发布
-
+
首页
死锁的产生、排查与解决方案
> 线程死锁通常是因为两个或两个以上线程在资源争夺中,形成循环等待,导致它们都无法继续执行各自后续操作的现象。 我们结合下图简单举个例子: - 线程1拥有资源A同时使用锁A进行锁定,并等待获取资源B; - 与此同时线程2拥有资源B同时使用锁B进行锁定,并等待获取资源A。 - 此时便形成了线程1和线程2相互等待对方先释放锁的现象,形成了死循环,最终导致死锁。  >i 死锁的产生必要条件 | 序号 | 必要条件 | 说明 | | --- | --- | --- | | 1 | `互斥条件` | 互斥即非此即彼,一个资源要不是我拥有,要不是你拥有,就是不能我们俩同时拥有。也就是互斥条件是指至少有一个资源处于非共享状态,一次只能有一个线程可以访问该资源 | | 2 | `占有并等待条件` | 该条件是指一个线程在拥有至少一个资源的同时还在等待获取其他线程拥有的资源。 | | 3 | `不可剥夺条件` | 该条件是指一个线程一旦获取了某个资源,则不可被强行剥夺对该资源的所有权,只能等待该线程自己主动释放。 | | 4 | `循环等待条件` | 循环等待是指线程等待资源形成的循环链,比如线程A等待资源B,线程B等待资源C,线程C等待资源A,但是资源A被线程A拥有,资源B被线程B拥有,资源C被线程C拥有,如此形成了依赖死循环,都在等待其他线程释放资源。 | >s 解决办法 - 1、顺序加锁 顺序加锁就是为了避免产生循环等待,如果大家都是先锁定lockA,再锁定lockB,则就不会产生循环等待。 - 2、使用尝试锁 我们可以使用一些其他锁机制,比如使用Monitor.TryEnter方法尝试获取锁,如果在指定时间内没有获取到锁,则释放当前所拥有的锁,以此来避免死锁。 - 3、使用超时机制 我们可以通过Thead结合CancellationToken实现超时机制,避免线程无限等待。当然可以直接使用Task,因为Task本身就支持CancellationToken,提供了内置的取消支持使用起来更方便。 - 4、避免嵌套使用锁 一个线程在拥有一个锁的同时尽量避免再去申请另一个锁,这样可以避免循环等待。
孙端己
2025年2月20日 00:15
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码