C#使用Monitor类实现线程同步
作者:農碼一生 发布时间:2021-07-20 03:01:14
一、简介
Lock关键字是Monitor的一种替换用法,lock在IL代码中会被翻译成Monitor.
lock (obj)
{
//代码段
}
//就等同于
Monitor.Enter(obj);
//代码段
Monitor.Exit(obj);
Monitor的常用属性和方法:
Enter(Object) 在指定对象上获取排他锁。
Exit(Object) 释放指定对象上的排他锁。
Pulse 通知等待队列中的线程锁定对象状态的更改。
PulseAll 通知所有的等待线程对象状态的更改。
TryEnter(Object) 试图获取指定对象的排他锁。
TryEnter(Object, Boolean) 尝试获取指定对象上的排他锁,并自动设置一个值,指示是否得到了该锁。
Wait(Object) 释放对象上的锁并阻止当前线程,直到它重新获取该锁。
常用的方法有两个
Monitor.Enter(object)方法是获取锁
Monitor.Exit(object)方法是释放锁
这就是Monitor最常用的两个方法,在使用过程中为了避免获取锁之后因为异常,致锁无法释放,所以需要在try{} catch(){}之后的finally{}结构体中释放锁(Monitor.Exit())。
二、代码
1.Enter(Object)案例
Enter(Object)的用法很简单,看代码
class Program
{
static void Main(string[] args)
{
Thread threadA = new Thread(ThreadMethod);
threadA.Name = "A";
Thread threadB = new Thread(ThreadMethod);
threadB.Name = "B";
threadA.Start();
threadB.Start();
Thread.CurrentThread.Name = "C";
ThreadMethod();
Console.ReadKey();
}
static object obj = new object();
public static void ThreadMethod()
{
Monitor.Enter(obj); //Monitor.Enter(obj) 鎖定对象
try
{
for (int i = 1; i <= 10; i++)
{
Console.Write(Thread.CurrentThread.Name + ":" + i + "\t");
}
Console.WriteLine();
}
catch (Exception ex)
{
}
finally
{
Monitor.Exit(obj); // Monitor.Exit(obj); 释放鎖定对象
}
}
}
执行结果:
2.TryEnter(Object)和TryEnter()案例
TryEnter(Object)和TryEnter()方法在尝试获取一个对象上的显式锁方面和 Enter()方法类似。然而,它不像Enter()方法那样会阻塞执行。如果线程成功进入关键区域那么TryEnter()方法会返回true. 和试图获取指定对象的排他锁。看下面代码演示:
class Program
{
static void Main(string[] args)
{
Thread threadA = new Thread(ThreadMethod);
threadA.Name = "A";
Thread threadB = new Thread(ThreadMethod);
threadB.Name = "B";
threadA.Start();
threadB.Start();
Thread.CurrentThread.Name = "C";
ThreadMethod();
Console.ReadKey();
}
static object obj = new object();
public static void ThreadMethod()
{
bool flag = Monitor.TryEnter(obj, 1000);
//设置1S的超时时间,如果在1S之内没有获得同步锁,则返回false
//上面的代码设置了锁定超时时间为1秒,也就是说:
//如果在1秒中后,lockObj还未被解锁,TryEntry方法就会返回false,如果在1秒之内,lockObj被解锁,TryEntry返回true。我们可以使用这种方法来避免死锁
try
{
if (flag)
{
for (int i = 1; i <= 10; i++)
{
Console.Write(Thread.CurrentThread.Name + ":" + i + "\t");
}
Console.WriteLine();
}
}
catch (Exception ex)
{
}
finally
{
if (flag)
Monitor.Exit(obj); // Monitor.Exit(obj); 释放鎖定对象
}
}
}
执行结果:
通过Monitor.TryEnter(monster, 1000),该方法也能够避免死锁的发生,我们上面的例子用到的是该方法的重载,Monitor.TryEnter(Object,Int32)。
三、总结
为了能避免多线程死锁的发生,尽量用TryEnter(Object)和TryEnter()方法在尝试获取一个对象上的显式锁。
来源:https://www.cnblogs.com/wml-it/p/14822252.html


猜你喜欢
- 一、概述Overview - LINQ to XML | Microsoft 官方文档LINQ to XMLLINQ to XML 是一种启
- C#客户端程序,生成后是一个exe,如果带有大量的dll,那么dll和exe会混乱在一起,看起来非常混乱,我们可以建立一个文件夹,把dll放
- 本文给大家介绍Activity的生命周期,如果大家学习过iOS的小伙伴的话,Activity的生命周期和iOS中ViewController
- 最近滑动验证码在很多网站逐步流行起来,一方面对用户体验来说,比较新颖,操作简单,另一方面相对图形验证码来说,安全性并没有很大的降低。当然到目
- 1.launch启动流程已知协程的启动方式之一是Globalscope.launch,那么Globalscope.launch的流程是怎样的
- 1. 人机对战要增添一个人机对战的模块, 最大的难点就是如何让人机知道下在什么位置是最好的, 不仅要具备进攻的能力, 还需要具备防守的能力.
- 重写java object类的equals方法覆盖equals方法请遵守约定什么情况下要覆盖equals方法容易违反的对称性不易察觉的传递性
- 经典排序算法 - 基数排序Radix sort原理类似桶排序,这里总是需要10个桶,多次使用首先以个位数的值进行装桶,即个位数为1则放入1号
- springboot整合vue实现上传下载文件,供大家参考,具体内容如下环境springboot 1.5.x完整代码下载:springboo
- Activity中Toast的使用Toast.makeText(this,"ADD",Toast.LENGTH_SHOR
- Android EditText限制输入字符的方法总结最近项目要求限制密码输入的字符类型, 例如不能输入中文。 &nb
- 目录前言1.设计模式:单例模式1.1 使用时分配,1.2 声明时实例化1.3 双检锁1.4 .net 特性保证的线程安全1.5 使用DI依赖
- 我们都知道mybatis在进行参数判断的时候,直接可以用<if test=""></if> 就可
- 关于“标签PDF文件(Tagged PDF)标签PDF文件包含描述文档结构和各种文档元素顺序的元数据,是一种包含后端提供
- 在常见场景下:返回数据建议使用map,不建议使用实体对象 /** * 1. 名字包含雨并且年龄小于40  
- 1.之前在使用AutoMapper 框架感觉用着比较不够灵活,而且主要通过表达式树Api 实现对象映射 ,写着比较讨厌,当出现复杂类型和嵌套
- Feign导入依赖为unknow的情况网上很多人在使用的feign时在pom.xml中的依赖为:<!-- SpringCloud 整合
- 本文实例为大家分享了UnityShader实现运动模糊的具体代码,供大家参考,具体内容如下原理:像素的当前帧的NDC坐标(x,y
- 不管eclipse有没有被被时代抛弃,反正是被我抛弃了,因为IDEA是真的好用现在公司的项目基本都是基于maven的多module项目,co
- 内容简介最近在用Unity实现无人机的模拟飞行,但发现站里基本没有完整介绍如何实现该功能的博客,因时间紧迫,就自己简单做了一个仿真(不是完全