.net core WebApi Mutex实现并发同步
Mutex,中文译为互斥体,在.net中也是作为一种线程或进程之间的互斥体存在。即在同一时刻,一个共享资源只允许被某一个线程或进程访问,其他线程或进程需要等待(直至获取互斥锁为止)。
Mutex的使用方式与Monitor很相似,但绝不相同。Monitor支持线程间并发同步,Mutex不但支持线程也支持进程间并发同步。
Mutex有许多需要注意的地方,如果稍不注意,则你会被坑惨!
接下来我们使用控制台和webapi项目各自做测试。
一、使用控制台测试进程间的同步
测试代码如下:
[STAThread]
static void Main(string[] args)
{
//使用指定名称为MName的互斥体
//如果获取到名称为MName的互斥体,则flag为true,否则为false。flag作用很大,如果是指定了互斥体的名称,一定要用flag去判断是否互斥。
Mutex mutex = new Mutex(true, "MName", out bool flag); if (flag) {
Console.WriteLine("1.获取互斥锁,开始运行");
Thread.Sleep();
Console.WriteLine("2.释放互斥锁!");
mutex.ReleaseMutex();
Console.WriteLine("3.开始等待,5秒后超时!");
if (mutex.WaitOne())
Console.WriteLine("6.获取互斥锁,开始运行!");
else Console.WriteLine("6.超时释放互斥锁!");
Thread.Sleep();
}
else {
Console.WriteLine("1.未获取互斥锁,开始等待!");
mutex.WaitOne();
Console.WriteLine("4.获取互斥锁,开始运行!");
Console.WriteLine("5.释放互斥锁!");
mutex.ReleaseMutex();
} Console.ReadKey();
}
同时打开两个程序的运行结果如下所示:

进程间的并发同步需要指定互斥体的名称,只要是同一个名称,它们就能互斥。
Mutex的WaitOne()方法是阻塞当前线程并等待获取互斥体。ReleaseMutex()方法是释放当前线程拥有的互斥体,如果当前进程或线程没有拥有互斥体Mutex,则会抛出System.ApplicationException异常,这点需要注意。
WaitOne和ReleaseMutex方法最好成对出现,反正单个方法两两不相见。
多个ReleaseMutex方法一起运行的异常见以下图片:

这个问题可以看ReleaseMutex方法的定义说明:
/// <summary>Releases the <see cref="T:System.Threading.Mutex"></see> once.</summary>
/// <exception cref="T:System.ApplicationException">The calling thread does not own the mutex.</exception>
/// <exception cref="T:System.ObjectDisposedException">The current instance has already been disposed.</exception>
public void ReleaseMutex();
产生System.ApplicationException异常的原因就是当前被调用的线程已经不拥有该互斥体!
二、使用WebApi项目测试线程间的同步
测试代码如下:
[HttpGet("[controller]/v1/api/[action]")]
public IActionResult Test() {
return Json(SynchronizationTest());
}
//指定一个互斥体名称
protected static string MutexName => "MName";
public ResponseModel SynchronizationTest() {
ResponseModel rc = new ResponseModel(, "初始化");
Mutex mutex = new Mutex(true, MutexName, out bool flag);
try {
//如果没有获取到互斥体,则等待,3秒后超时。如果获取到了互斥体,则flag=true,否则flag=false。一定要做flag判断,否则会抛出异常
if(!flag)
mutex.WaitOne();
int count = RedisHelper.Get(GoodsNumberKey).ToInt32();
if (count > ) {
RedisHelper.Set(GoodsNumberKey, "-1");
rc.SetMessage("重置成功!");
}
else rc.SetMessage("已被重置,本次重置无效");
rc.SetCode(Thread.CurrentThread.ManagedThreadId);
}
catch (Exception ex) {
_log.Error(ex);
}
finally {
mutex.ReleaseMutex();
mutex.Close();
mutex.Dispose();
}
return rc;
}
接下来,我们使用如下代码连续发送8次请求
HttpHelper.GetOnStringAsync($"{Url}/Shop/v1/api/Test", contentType: "application/json").ContinueWith(it =>
{
Console.WriteLine(it.Result);
});
测试的结果如下图所示:

可以看见,我们连续发送8次请求,只有一次重置成功,其他的都因为互斥的关系而重置无效。
.net core WebApi Mutex实现并发同步的更多相关文章
- .net core WebApi ManualResetEvent实现并发同步
ManualResetEvent,即手动重置事件,通过信号量来判别当前线程是否应该阻塞或继续执行.使用方式与ManualResetEventSlim差不多,ManualResetEventSlim只是 ...
- .net core WebApi Monitor实现并发同步
在.net中,还可以使用Monitor实现线程并发同步.Monitor类是纯托管且完全可移植,并且可能会在操作系统资源需求方面更加高效. Monitor的锁对象尽可能使用引用对象,如果是字符串或值对象 ...
- .Net Core WebAPI 基于Task的同步&异步编程快速入门
.Net Core WebAPI 基于Task的同步&异步编程快速入门 Task.Result async & await 总结 并行任务(Task)以及基于Task的异步编程(asy ...
- Net Core WebAPI
Net Core WebAPI .Net Core WebAPI 基于Task的同步&异步编程快速入门 Task.Result async & await 总结 并行任务(Task)以 ...
- .net core WebApi Interlocked配合ManualResetEventSlim实现并发同步
由于项目有某种需求,在WebApi中,有大量的请求需要操作相同的数据,因此需要用到并发同步机制去操作共享的数据. 本次配合使用Interlocked和ManualResetEventSlim来实现并发 ...
- net core WebApi——文件分片下载
目录 前言 开始 测试 小结 @ 前言 上一篇net core WebApi--文件分片上传与跨域请求处理介绍完文件的上传操作,本来是打算紧接着写文件下载,中间让形形色色的事给耽误的,今天还是抽个空整 ...
- ASP.NET Core WebAPI控制器返回类型的最佳选项
前言 从.NET Core 2.1版开始,到目前为止,控制器操作可以返回三种类型的WebApi响应.这三种类型都有自己的优点和缺点,但都缺乏满足REST和高可测性的选项. ASP.NET Core中可 ...
- ASP.NET Core WebApi使用Swagger生成api说明文档
1. Swagger是什么? Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件 ...
- 使用 xUnit 编写 ASP.NET Core WebAPI单元测试
本文使用xUnit对ASP.NET Core WebAPI做单元测试,使用HttpClient的同步和异步请求,下面详细介绍xUnit的使用过程: 一.创建示例项目 模板为我们自动创建了一个Value ...
随机推荐
- gateway + jwt 网关认证
思路: 全局过滤器对所有的请求拦截(生成token有效期30分钟,放入redis设置有效期3天.3天之类可以通过刷新接口自动刷新,超过3天需要重新登录.) 前端在调用接口之前先判断token是否过期( ...
- linux下目录的作用
FHS针对目录树架构仅定义出三层目录底下应该放置什么数据而已,分别是底下这三个目录的定义: / (root, 根目录):与开机系统有关: /usr (unix software resource):与 ...
- day08 python之函数初识
一,什么是函数? 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print(),len( ...
- AJAX理解
注:首先我们要明白请求是什么?请求分两种,一.静态请求(如:返回js.css.图片等) 二.动态请求(返回跟用户有关的数据) http(apache.nginx等)服务器会判断如果是一个静态请求,会直 ...
- kettle 连接 Oracle 异常
场景重现 新安装的 kettle(pdi-ce-7.0.0.0-25) 连接 Oracle 11G R2 报错如下: 解决办法 到 Oracle 官网 JDBC Downloads 下载对应的 ojd ...
- FFT 快速傅里叶变换 学习笔记
FFT 快速傅里叶变换 前言 lmc,ikka,attack等众多大佬都没教会的我终于要自己填坑了. 又是机房里最后一个学fft的人 早背过圆周率50位填坑了 用处 多项式乘法 卷积 \(g(x)=a ...
- 6、zabbix使用进阶(02)
zabbix知识点: zabbix可视化 自定义图形(graphs) 屏幕(screen) 宏(macros) 用户参数(User parameters):用户自定义items key的方式来实现自 ...
- C# 绘图
e.Graphics.DrawLine (绘制一条连接由坐标对指定的两个点的线条) e.Graphics.DrawString (绘制指定位置的文本字符串) e.Graphics.DrawRectan ...
- 3.1 eureka自我保护
故障现象: Down:是下线(掉线)的意思. 导致原因: 一句话:某时刻某一个微服务不可用了,eureka不会立刻清理,依旧会对该微服务的信息进行保存 什么是自我保护模式? 默认情况下,如果Eurek ...
- Web开发中button与submit区别
submit是button的一个特例,也是button的一种,它把提交这个动作自动集成了. 如果表单在点击提交按钮后需要用JS进行处理(包括输入验证)后再提交的话,通常都必须把submit改成butt ...