C#线程同步与死锁Monitor
在上一讲介绍了使用lock来实现C#线程同步。实际上,这个lock是C#的一个障眼法,在C#编译器编译lock语句时,将其编译成了调用Monitor类。先看看下面的C#源代码:
- public static void MyLock()
- {
- lock (typeof(Program))
- {
- }
- }
上面的代码通过lock语句使MyLock同步,这个方法被编译成IL后,代码如图1所示。

图1
从上图被标注的区域可以看到,一条lock语句被编译成了调用Monitor的Enter和Exit方法。Monitor在 System.Threading命名空间中。lock的功能就相当于直接调用Monitor的Entry方法,所不同的是,lock方法在结束后,会自动解除锁定,当然,在IL中是调用了Monitor的Exit方法,但在C#程序中,看起来是自动解锁的,这类似于C#中的using语句,可以自动释放数据库等的资源。但如果直接在C#源程序中使用Monitor类,就必须调用Exit方法来显式地解除锁定。如下面的代码所示:
- Monitor.Entry(lockObj);
- try
- {
- // lockObj的同布区
- }
- catch(Exception e)
- {
- // 异常处理代码
- }
- finally
- {
- Monitor.Exit(lockObj); // 解除锁定
- }
Exit方法最后在finally里调用,这样无论在方法在发生异常、返回还是正常执行,都会执行到finally,并调用Exit方法解除锁定。
Monitor类不仅可以完全取代lock语句(如果只使用lock语句本身的功能,最好还是直接用lock语句吧),还可以使用TryEntry方法设置一个锁定超时,单位是毫秒。如下面的代码所示:
- if(Monitor.TryEntry(lockObj, 1000))
- {
- try
- {
- }
- finally
- {
- Monitor.Exit(lockObj);
- }
- }
- else
- {
- // 超时后的处理代码
- }
上面的代码设置了锁定超时时间为1秒,也就是说,在1秒中后,lockObj还未被解锁,TryEntry方法就会返回false,如果在1秒之内,lockObj被解锁,TryEntry返回true。我们可以使用这种方法来避免死锁,如下面的代码所示:
- class Program
- {
- private static Object objA = new Object();
- private static Object objB = new Object();
- public static void LockA()
- {
- if (Monitor.TryEnter(objA, 1000))
- {
- Thread.Sleep(1000);
- if (Monitor.TryEnter(objB, 2000))
- {
- Monitor.Exit(objB);
- }
- else
- {
- Console.WriteLine("LockB timeout");
- }
- Monitor.Exit(objA);
- }
- Console.WriteLine("LockA");
- }
- public static void LockB()
- {
- if (Monitor.TryEnter(objB, 2000))
- {
- Thread.Sleep(2000);
- if (Monitor.TryEnter(objA, 1000))
- {
- Monitor.Exit(objA);
- }
- else
- {
- Console.WriteLine("LockA timeout");
- }
- Monitor.Exit(objB);
- }
- Console.WriteLine("LockB");
- }
- public static void Main()
- {
- Thread threadA = new Thread(LockA);
- Thread threadB = new Thread(LockB);
- threadA.Start();
- threadB.Start();
- Thread.Sleep(4000);
- Console.WriteLine("线程结束");
- }
- }
上面的代码是在上一讲举的死锁的例子,但在这一讲将lock语句改成了TryEntry方法,而且设置了锁定超时间,由于在等待一定时间后,不管被锁定的对象是否被解锁,TryEntry方法都会返回,因此,上面的代码是不会死锁的。运行上面的代码的结果如图2所示。

图2
如果TryEntry方法的超时时间为System.Threading.Timeout.Infinite,TryEntry方法就相当于Entry方法,如果超时时间为0,不管是否解锁,TryEntry方法都会立即返回。
这样就解决了C#线程同步与死锁的问题
C#线程同步与死锁Monitor的更多相关文章
- C#:多线程、线程同步与死锁
推荐阅读: C#线程系列讲座(1):BeginInvoke和EndInvoke方法 C#线程系列讲座(2):Thread类的应用 C#线程系列讲座(3):线程池和文件下载服务器 C#线程系列讲座(4) ...
- 线程同步 – lock和Monitor
在多线程代码中,多个线程可能会访问一些公共的资源(变量.方法逻辑等等),这些公共资源称为临界区(共享区):临界区的资源是不安全,所以需要通过线程同步对多个访问临界区的线程进行控制. 同样,有些时候我们 ...
- Java之线程,常用方法,线程同步,死锁
1, 线程的概念 进程与线程 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程.(进程是资源分配的最小单位) 线程:同一类线程共享代码和数据 ...
- java 线程同步、死锁
转载地址:速学堂 https://www.sxt.cn/Java_jQuery_in_action/eleven-thread-synchronization.html 什么是线程同步 同步问题的提 ...
- java ->多线程_线程同步、死锁、等待唤醒机制
线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. l 我们通过一个案例,演示线 ...
- Java线程同步与死锁认识
讲下自己的认识,算小小的总结吧! synchroized 具有同步线程的功能,它的处理机制类似于给参数里面的对象赋一个标记值,来表明当前状态,当程序里面某个线程执行synchroized里面的代码段时 ...
- C# 线程同步之排它锁/Monitor监视器类
一.Monitor类说明,提供同步访问对象的机制. 1.位于System.Threading命名空间下,mscorlib.dll程序集中. 2.Monitor通过获取和释放排它锁的方式实现多线程的同步 ...
- 线程同步、死锁和通信——Java多线程(二)
一.多线程同步 上一篇随笔中,我曾遇到对多线程程序的多次运行结果不一致的情况,这主要是因为没有对这些线程在访问临界资源做必要的控制,而接下来就用线程的同步来解决这个问题. 1.同步代码块 class ...
- 四十四、Linux 线程——线程同步之死锁以及线程和信号
44.1 死锁 死锁: 两个线程试图同时占有两个资源,并按不同的次序锁定相应的共享资源 解决方式: 按相同的次序锁定相应的共享资源 使用函数 pthread_mutex_trylock(),它是函数 ...
随机推荐
- R语言实战(六)重抽样与自助法
本文对应<R语言实战>第12章:重抽样与自助法 之前学习的基本统计分析.回归分析.方差分析,是假定观测数据抽样自正态分布或者其他性质较好的理论分布,进而进行的假设检验和总体参数的置信区间估 ...
- The file will have its original line endings in your working directory.
在空仓库的情况下,add,出现一下问题 The file will have its original line endings in your working directory. 当报这个警告时是 ...
- Bazel
Using Bazel on Windows Google软件构建工具Bazel FAQ
- C#连接操作MySQL数据库详细步骤 帮助类等(二次改进版)
最近准备写一个仓库管理的项目 客户要求使用C#编写MySQL存储数据 为了方便,整理了数据库操作的工具类 首先在项目App.config 文件下添加节点 <connectionStrings&g ...
- JAVA基础部分面试
1:面向对象编程有很多重要的特性: 封装,继承,多态和抽象. 2:什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? (1)Java虚拟机是一个可以执行Java字节码的虚拟机进程.J ...
- H5 video标签视频加载存在的问题
客户发现上传的视频无法播放,然后主管让我解决这个问题,这个页面不是我负责的,我看了代码,发现视频用的h5标签video标签加载视频.我看了没问题,然后 我先用ie浏览器打开,视频加载没问题.然后我给主 ...
- python脚本 pyqt 打包成windows可执行exe文件 pyinstaller
今天学习pyqt,做了一些好玩的东西. 好奇之中想试试python脚本编译成可执行文件,一顿查询之后成功了! 我的环境是: windows10 64bit python3.5 pyqt5 ...
- Alpha7
难受
- Vue基础知识简介
基础知识: vue的生命周期: beforeCreate/created.beforeMount/mounted.beforeUpdate/updated.beforeDestory/destorye ...
- 【Eclipse提高开发速度-插件篇】安装多语言Propertys编辑工具
安装的的时候能够通过 Help>Eclipse Marketplace的 搜索方式安装 或者 Help>Install New Software Name:Propertys URL:ht ...