由于项目有某种需求,在WebApi中,有大量的请求需要操作相同的数据,因此需要用到并发同步机制去操作共享的数据。

本次配合使用Interlocked和ManualResetEventSlim来实现并发同步的目的。

Interlocked实现了原子性的操作,ManualResetEventSlim提供信号量等待唤醒机制。

以上两个关键字,自行找度娘了解。

代码如下:

        [HttpGet("[controller]/v1/api/[action]")]
public IActionResult Test() {
return Json(SynchronizationTest());
} protected static int Counter = ;//1:空闲 0:非空闲
protected static ManualResetEventSlim Mres = new ManualResetEventSlim(false);
public ResponseModel SynchronizationTest() {
ResponseModel rc = new ResponseModel(, "初始化"); try {
//重置信号量,相当于灭灯
Mres.Reset();
//如果其他线程正在操作,则等待,5秒后超时
if (Interlocked.CompareExchange(ref Counter, , ) == )
Mres.Wait(); int count = RedisHelper.Get(GoodsNumberKey).ToInt32();
if (count > ) {
RedisHelper.Set(GoodsNumberKey, "-1");
rc.SetMessage("重置成功!");
}
else rc.SetMessage("已被重置,本次重置无效");
}
catch (Exception ex) {
_log.Error(ex);
}
finally {
//转为空闲状态
Interlocked.Exchange(ref Counter, );
//设置信号量,让上面的 Mres.Wait(5000);取消等待,继续执行代码。相当于亮灯
Mres.Set();
} return rc;
}

逻辑是:如果Counter为0(非空闲),则证明已经有其他线程先一步进入当前逻辑,则当前线程需要等待5秒钟(5秒钟超时后继续执行代码),finally中的代码表示执行完后会将Counter置为1(空闲)并唤醒其他等待的线程,让其他线程在超时之前继续执行。

注意:信号量事件(ManualResetEventSlim)对象要用同一个的Wait、Reset和Set配合才会实现并发同步的效果。

相关代码解释:

Interlocked.CompareExchange(ref int number,int firstValue,int secondValue);该方法一共有三个参数,作用是:如果number和secondValue相等,则将firstValue引用赋值给number,否则不做任何操作,之后会返回number的原始值。参考如下代码:

int tmp = number;
ref number = number==secondValue?firstValue:number;
return tmp;

Interlocked.Exchange(ref int number,int value)的作用是将value引用赋值给number,并返回number的原始值。

ManualResetEventSlim Mres = new ManualResetEventSlim(false),ManualResetEventSlim的构造函数,如果参数为true,则当前对象拥有信号量,如果为false,则不拥有信号量。ManualResetEventSlim的作用就是通过信号量的判别,是否阻塞当前线程。如果不拥有信号量,则Wait()方法可以让当前线程阻塞,一旦拥有了信号量,就结束Wait()方法的执行,并沿着当前代码继续执行下去。

ManualResetEventSlim.Reset()的作用是释放当前事件对象的信号量,接着调用其Wait()方法会阻塞当前线程。

ManualResetEventSlim.Set()的作用是让当前事件对象拥有信号量,可以让当前线程继续执行。

最新文章

  1. Android事件分发机制浅谈(一)
  2. JSTL函数标签库 fn标签
  3. js-JavaScript高级程序设计学习笔记11
  4. Django~Models1
  5. FEE Development Essentials
  6. list和set的区别
  7. linux系统主要常见目录结构
  8. 数据库实例创建好后,用plsql登录居然提示ora-12526监听程序:所有适用例程都处于受限模式的问题
  9. 【C#】索引器
  10. Linux内核初始化定义
  11. Java---StringBuffer()方法的简单应用
  12. 【Thinkphp 5】auth权限设置以及实现
  13. 百度前端技术学院js任务三
  14. Android 打造编译时注解解析框架 这只是一个开始
  15. 初尝Spring Cloud Config
  16. Chapter 7 Resources in Plug-In(1)
  17. 转://Oracle 事务探索与实例(二)
  18. Parquet 格式文件
  19. MySQL--lsblk命令查看块设备
  20. 爬虫基础库之beautifulsoup的简单使用

热门文章

  1. 揭开yield关键字的神秘面纱
  2. codeforces 985E Pencils and Boxes
  3. Angular4 HTTP通讯
  4. 怎么让table中的<td>内容向上对齐
  5. Always clear download 下载 谷歌浏览器插件
  6. mvc 之 RouteConfig配置
  7. vue-cli 构建项目在IE中无法运行解决方式(build之后可运行)
  8. JavaScript(数据类型、字符串操作)
  9. Asp.net core 学习笔记 2.1 升级到 2.2
  10. RabbitMQ(5)FanoutExchange