利用 Monitor.TryEnter 来规避 .NET 线程死锁的源代码
在开发多线程的应用程序时,我们会大量用到 lock (...) {} 块。如果 lock 的对象比较多,非常容易发生死锁。死锁的发生很难预料,而且一旦发生在界面线程上,界面就不再刷新响和应用户输入;如果发生在后台线程,后台线程也就阻塞不工作了,死锁必然会导致应用程序不可用。在.NET里发生死锁的原因是什么?
以 C# 为例,通常 lock 语句是被转化为对一个资源的无限长时间的等待,所以一旦资源被占用而又永不释放,那么必然死锁。
那么如何规避的危害呢?应用程序应该避免 lock(obj) 块,推荐使用 Monitor.TryEnter(obj, millisecondsTimeout) 代替,二者的第一个参数意义相同,而后者还可以设置等待超时时间,一旦在限定的时间内无法获得锁,那么 TryEnter 就会返回 false。这样就不会造成死锁,无法获得资源,业务程序可以采取重试或抛异常的方式进行善后处理。
Monitor.TryEnter 和 Monitor.Exit 必须成对出现,为了简化代码,可以用一个实现IDisposeable的类来封装这个过程:
/// <summary>
/// 会自动释放的锁,可设置等待超时
/// </summary>
public class Lock : IDisposable
{
/// <summary>
/// 默认超时设置
/// </summary>
public static int DefaultMillisecondsTimeout = 15000; // 15S
private object _obj;
/// <summary>
/// 构造
/// </summary>
/// <param name="obj">想要锁住的对象</param>
public Lock(object obj)
{
TryGet(obj, DefaultMillisecondsTimeout, true);
}
/// <summary>
/// 构造
/// </summary>
/// <param name="obj">想要锁住的对象</param>
/// <param name="millisecondsTimeout">超时设置</param>
public Lock(object obj, int millisecondsTimeout)
{
TryGet(obj, millisecondsTimeout, true);
}
/// <summary>
/// 构造
/// </summary>
/// <param name="obj">想要锁住的对象</param>
/// <param name="millisecondsTimeout">超时设置</param>
/// <param name="throwTimeoutException">是否抛出超时异常</param>
public Lock(object obj, int millisecondsTimeout, bool throwTimeoutException)
{
TryGet(obj, millisecondsTimeout, throwTimeoutException);
}
private void TryGet(object obj, int millisecondsTimeout, bool throwTimeoutException)
{
if (Monitor.TryEnter(obj, millisecondsTimeout))
{
_obj = obj;
}
else
{
if (throwTimeoutException)
{
throw new TimeoutException();
}
}
}
/// <summary>
/// 销毁,并释放锁
/// </summary>
public void Dispose()
{
if (_obj != null)
{
Monitor.Exit(_obj);
}
}
/// <summary>
/// 获取在获取锁时是否发生等待超时
/// </summary>
public bool IsTimeout
{
get
{
return _obj == null;
}
}
}
调用例子:
using (Lock l = new Lock(obj, 10000))
{
....
}
这样在代码离开 using 块后,会自动执行 Monitor.Exit释放锁。
是不是很棒? :)
利用 Monitor.TryEnter 来规避 .NET 线程死锁的源代码的更多相关文章
- 《C#多线程编程实战》1.11 Monitor.TryEnter()避免死锁
这章的内容是真的有意思 特别是代码. 先贴上代码: class Program { static void Main(string[] args) { object lock1 = new objec ...
- 线程系列08,实现线程锁的各种方式,使用lock,Montor,Mutex,Semaphore以及线程死锁
当涉及到多线程共享数据,需要数据同步的时候,就可以考虑使用线程锁了.本篇体验线程锁的各种用法以及线程死锁.主要包括: ※ 使用lock处理数据同步※ 使用Monitor.Enter和Monitor.E ...
- .net学习之多线程、线程死锁、线程通信 生产者消费者模式、委托的简单使用、GDI(图形设计接口)常用的方法
1.多线程简单使用(1)进程是不执行代码的,执行代码的是线程,一个进程默认有一个线程(2)线程默认情况下都是前台线程,要所有的前台线程退出以后程序才会退出,进程里默认的线程我们叫做主线程或者叫做UI线 ...
- 对象及变量的并发访问(同步方法、同步代码块、对class进行加锁、线程死锁)&内部类的基本用法
主要学习多线程的并发访问,也就是使得线程安全. 同步的单词为synchronized,异步的单词为asynchronized 同步主要就是通过锁的方式实现,一种就是隐式锁,另一种是显示锁Lock,本节 ...
- Python并发编程-进程 线程 同步锁 线程死锁和递归锁
进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ...
- Atitit.线程 死锁 跑飞 的检测与自动解除 与手动解除死锁 java c# .net php javascript.
Atitit.线程 死锁 跑飞 的检测与自动解除 与手动解除死锁 java c# .net php javascript. 1. 现象::主程序卡住无反应,多行任务不往下执行 1 2. 原因::使用j ...
- Python3 进程 线程 同步锁 线程死锁和递归锁
进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ...
- java 线程死锁的检测
java 线程死锁的检测 例子程序: import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executo ...
- troubleshoot之:用control+break解决线程死锁问题
目录 简介 死锁的代码 control+break命令 Full thread dump 死锁检测 Heap信息 总结 简介 如果我们在程序中遇到线程死锁的时候,该怎么去解决呢? 本文将会从一个实际的 ...
随机推荐
- 用python实现简单EXCEL数据统计的实例
用python实现简单EXCEL数据统计的实例 下面小编就为大家带来一篇用python实现简单EXCEL数据统计的实例.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧 任 ...
- EF中where中日期帅选问题
结合 SqlFunctions 和 DbFunctions 不能同时用两个DbFunctions queryAble = queryAble.Where(s=> SqlFunctions.D ...
- 【笔记】Docker部署Odoo
一,制作一个自己的odoo镜像odoo:yto 1,下载一个odoo10的镜像 docker pull odoo:10.0 2,按照自己的意愿修改里面的内容 docker run -it -u roo ...
- 撸了一个简易的工具库: jeasy
一年前,发现在工作的项目中存在大量使用monment的情况,但仅使用到最基础的format功能.monment的体积直接导致项目体积成倍增加,于是jeasy就诞生了. jeasy实现了monment最 ...
- 深入理解C语言-深入理解void
void的字面意思是"无类型",void *则为"无类型指针",void *可以指向任何类型的数据 void含义 void几乎只有注释和限制程序的作用,定义一个 ...
- vue中使用raphael.js实现地图绘制
一.效果图 二.在vue中引入raphael.js npm i raphael -S 三.封装一个名为StreetMap的组件,代码如下 <template> <div> &l ...
- nginx多线程高并发
直接上图 Master-Worker模式 1.Nginx 在启动后,会有一个 master 进程和多个相互独立的 worker 进程. 2.接收来自外界的信号,向各worker进程发送信号,每个进程都 ...
- 2019牛客暑期多校训练营(第七场)-B Irreducible Polynomial(多项式因式分解)
题目链接:https://ac.nowcoder.com/acm/contest/887/B 题意:给定整系数多项数,判断实数域上是否可约. 思路: AC代码: #include<cstdio& ...
- 链表操作Java实现
单链表 存储结构 public class ListNode { int i; ListNode next; ListNode(int i) { this.i = i; } public String ...
- ssm中静态文件加载路径
项目在本地软件和在服务器上的项目路径如果写死,有可能会出现项目在本机上可以访问,架设在服务器上后就不能访问 这儿介绍在ssm框架中使用 @WebServlet(urlPatterns = {},loa ...