C#线程同步

embedded/2024/11/13 9:30:47/

c#线程同步代码示例

仔细考虑下面这段代码是不是输出0

    const int _max = 1000000;private int _count = 0;void Start(){Task task = Task.Run(() =>{Decr();});for (int i = 0; i < _max; i++){_count++;}task.Wait();Debug.Log(_count);}void Decr(){for(int i = 0; i < _max; i++){_count--;}}

下面这个代码呢

const int _max = 1000000;private int _count = 0;object _sync = new object();void Start(){Task task = Task.Run(() =>{Decr();});for (int i = 0; i < _max; i++){lock (_sync){_count++;   }}task.Wait();Debug.Log(_count);}void Decr(){for(int i = 0; i < _max; i++){lock (_sync){_count--;   }}

将要访问_Count的代码段锁定了之后(用lock)​,Main()和Decr()方法就是线程安全的。换言之,可从多个线程中同时安全地调用它们

即使为了同步的需要可以忍受lock的速度,也不要在多处理器计算机中不假思索地添加同步来避免死锁和不必要的同步(也许本来可以并行执行的)​。

object 必须是引用类型的对象。如果你尝试将一个值类型(如结构体或基本数据类型如 int)作为 lock 语句的参数,编译器会报错。例如:

int myLock = 0;
lock (myLock) // 编译错误:不能将值类型作为 lock 的参数
{// 代码
}

这会导致编译错误,因为 myLock 是一个 int,它是一个值类型。正确的做法是使用一个引用类型的对象作为锁

为什么要避免锁定this、typeof(type)和string

一个貌似合理的模式是锁定代表类中实例数据的this关键字,以及为静态数据锁定从typeof(type)(例如typeof(MyType))获取的类型实例。在这种模式下,使用this可为与特定对象实例关联的所有状态提供同步目标;使用typeof(type)则为一个类型的所有静态数据提供同步目标。但这样做的问题在于,在另一个完全不相干的代码块中,可能创建一个完全不同的同步块,而这个同步块的同步目标可能就是this(或typeof(type))所指向的同步目标。换言之,虽然只有实例自身内部的代码能用this关键字来阻塞,但创建实例的调用者仍可将那个实例传给一个同步锁。

简单来说  经常锁定this,调用者无意间可能也把这个对象当作锁,有死锁的隐患

要避免的另一个锁定类型是string,这是因为要考虑到字符串留用问题。如同一个字符串常量在多个位置出现,那么所有位置都可能引用同一个实例,使锁定的范围大于预期

将字段声明为volatile

编译器和/或CPU有时会对代码进行优化,使指令不按照它们的编码顺序执行,或干脆拿掉一些无用指令。若代码只在一个线程上执行,像这样的优化无伤大雅。但对于多个线程,这种优化就可能造成出乎预料的结果,因为优化可能造成两个线程对同一字段的读写顺序发生错乱。

解决该问题的一个方案是用volatile关键字声明字段。该关键字强迫对volatile

字段的所有读写操作都在代码指示的位置发生,而不是在通过优化而生成的其他某个位置发生。volatile修饰符指出字段容易被硬件、操作系统或另一个线程修改。所以这种数据是“易变的”​(volatile)​,编译器和“运行时”要更严谨地处理它。

一般很少使用volatile修饰符。即便使用,也可能因为疏忽而使用不当。lock比volatile更好,除非对volatile的用法有绝对的把握。


http://www.ppmy.cn/embedded/107158.html

相关文章

YOLOv9改进策略【注意力机制篇】| 引入Shuffle Attention注意力模块,增强特征图的语义表示

一、本文介绍 本文记录的是基于Shuffle Attention注意力模块的YOLOv9目标检测改进方法研究。Shuffle Attention模块通过独特的设计原理&#xff0c;在保持轻量级的同时实现了高效的特征注意力机制&#xff0c;增强了网络的表示能力。本文对YOLOv9的RepNCSPELAN4模块进行二次创…

EmguCV学习笔记 C# 9.2 VideoWriter类

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。 教程VB.net版本请访问…

EPLAN中如何将图纸导出为PDF文件并设置页边距?

EPLAN中如何将图纸导出为PDF文件并设置页边距? 如下图所示,在项目中选中需要导出的图纸页, 如下图所示,点击上方页-----导出------PDF, 如下图所示,在弹出的窗口中设置导出文件的名称、输出目录、输出颜色,这里建议勾选“使用打印边距”, 如下图所示,继续点击下方的设…

python reques使用案例

python数据类型简介 2024/9/3 08:59:28 python数据类型简介 2024/9/3 08:59:32 你想了解哪种数据类型&#xff1f;如数字、字符串、列表等&#xff0c;还是有其他特定的类型或用法吗&#xff1f; 2024/9/3 08:59:40 所有的 2024/9/3 08:59:48 Python的主要数据类型包括&#xf…

Pencils Protocol生态新进展,即将上线 Vault 产品

“极高的盈利预期、通证的持续回购与销毁&#xff0c;Vault产品的推出正在成为Pencils Protocol生态发展的重磅利好。” Pencils Protocol是目前Scroll生态TVL最高的DeFi平台 &#xff0c;即便是行情整体较为平淡&#xff0c;其仍旧能够保持在3亿美元左右的锁仓价值&#xff0c…

?.操作符的作用

在编程中&#xff0c;?. 操作符通常被称为“可选链”&#xff08;Optional Chaining&#xff09;操作符&#xff0c;它主要用于JavaScript等现代编程语言中。这个操作符的主要作用是安全地访问深层嵌套的属性或方法&#xff0c;而无需在每一步都进行繁琐的null或undefined检查…

帆软报表使用url访问报表,自定义前端搜索,优化报表展示

近期公司页面往报表方向迁移&#xff0c;正好选择了帆软报表&#xff0c;由我负责这一部分的业务代码修改&#xff0c;我们没有采用帆软的鉴权模式。再进行简单的报表展示后发现原始的帆软报表组件不符合前端的设计要求&#xff0c;查询帆软官网后发现要修改是比较繁琐的。 先看…

部署mongosh教程

1、上传软件包 将软件包上传到/usr/local目录下 部署 2.1 解压 tar zxvf mongosh-2.3.0-linux-x64.tgz 2.2 修改名称 mv mongosh-2.3.0-linux-x64/ mongosh 2.3 将 bin 目录中 mongosh 二进制文件复制到 PATH 变量中列出的目录中 sudo cp mongosh /usr/local/bin/ sudo cp …