有关多线程环境下的Volatile、lock、Interlocked和Synchronized们

2023-10-28 20:12

本文主要是介绍有关多线程环境下的Volatile、lock、Interlocked和Synchronized们,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • 📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!
  • 📢本文作者:由webmote 原创
  • 📢作者格言:新的征程,我们面对的不仅仅是技术还有人心,人心不可测,海水不可量,唯有技术,才是深沉黑夜中的一座闪烁的灯塔 !

序言


多线程下的变量访问,就如同脚踏几只船的海王,在其精细的时间管理下安排每一个女朋友约会,一不小心,就很可能打翻友谊的小船,彻底坠入无尽的大海深处…

而为了让各位亲爱的猿们,在约会对象之间横跳的时候,能优雅的控制住频率,编程语言引入了多个关键字和对象类完成相关操作。

让我们逐个看看,这些概念都能完成什么样的奇葩事件吧!

1. Volatile 修饰符关键字

volatile 关键字通常被用来表示一个字段的值很可能被多个线程修改,因此在编译器(VS)编译时不要进行优化,也不被缓存在编译器或硬件寄存器里。

volatile 关键字,确保每次读取和写入时,其值都是直接从内存中拿出来的,避免任何的优化和缓存。

volatile 关键字标识的信息,就如同海王的A女友信息,每次海王想知道A女友的信息时,都显示的是A的最新信息,而不是从其他人打探的过时信息。有了第一手的信息,才能最大程度的避免不慎翻船。

让我们来个模拟例子吧,由于编译器的优化,准备这个例子着实不易。

//让我们在.net6下测试下...
Console.WriteLine("开始测试...");
var test = new Test();
new Thread(delegate () { Thread.Sleep(500); test.foo = 255; }).Start();
while (test.foo != 255) ;
Console.WriteLine("不好了,A女友正在抵达战场!");
Console.ReadLine();public class Test
{public int foo = 0;
}

如果你运行在Debug版本下,这时候你是可以收到A女友的抵达信息的。但是一旦你发布成Release,这个时候,命运的齿轮开始转动,你忽然收不到重要的抵达信息了,随着时间滴答滴答流动,危险的气息扑面而至。

你也试试看,切换到Release版本,按Ctrl+F5, 界面如下:

在这里插入图片描述
这个时候,volatile关键字的重要性就体现出来了,我们修改下如下信息:

public class Test
{public volatile int foo = 0;
}

在这里插入图片描述
看吧,一个volatile,就救了你一条命。

volatile的使用注意事项:

  • volatile关键字通常用于多线程应用程序中,用于处理由多个线程同时访问的共享字段。
  • volatile不用于同步;它仅确保单个读取和写入操作的可见性和原子性。如果需要同步来强制执行顺序或互斥,请考虑使用其他同步机制,如lock,Monitor,Semaphore
  • 在多线程方案中处理共享数据时,通常建议使用lock 关键字或其他原子操作类,因为仅使用volatile关键字可能不足以满足复杂的同步要求。
  • volatile`关键字用于字段修饰,一般常用的是整型、布尔、指针,当然还有引用类型(一般指地址)

一般关闭线程的布尔值是最佳使用场景。

单例的双重检查锁场景也是有用的,例如:

public class Singleton {
private static volatile Singleton _instance = null; 
private static Object _locker = new Object();
public static Singleton GetSingleValue()
{if (_instance == null){lock(_locker){if (_instance == null){ _ instance = new Singleton(); }}}return _ instance;
}

当然,有更简单的写法,那就是利用Lazy

public class Singleton
{private static readonly Lazy<Singleton> _instance= new Lazy<Singleton>(() => new Singleton());private Singleton(){}public static Singleton Instance{get{return _instance.Value;}}
}

2. Lock 锁,锁住要锁的人

lock,是最好用的保护机制之一了。 锁住资源,让其他线程都在后面排队,这样就不会撞到一块了。

在这里插入图片描述
话说,海王的日程表,必须有锁,没有锁的海王都死翘翘了。

这里是个简单的例子:

private object mylock = new object();public int A {get {int result;lock(mylock) {result = mA; }return result;} set { lock(mylock) { mA = value; }}
}

作为演示,这个例子足够简单;作为深度学习,这个例子并不好。

大部分类的属性都不需要lock操作,使用 public DateTime CreatedTime{get;set;}就已经足够了。因为基础类型都是原子操作的,因此没必要去锁定,除非你在get,set里有更复杂的操作。

因此,大可不必都增加上lock, 如果是多个线程访问,那么不妨增加上 volatile,当然,属性没法直接增加,有需要多写代码了。

3.Interlocked 非锁的原子操作

锁是独一无二的,那么对于时间管理大师们,来说,这并不是好消息。

那么有什么其他办法,既能满足大师们同时多个骚操作,又能正常而及时的得到通知呢?那就不得不提Interlocked 了,经济实惠,的确是居家旅行必备良词。

public class NuclearPowerPlant
{private long _meltdownIsHappening = 0;public bool MeltdownIsHappeningRightNow {get{/* 锁定操作仅仅支持整型,那么我们使用它替换布尔。*/return Interlocked.Read(ref _meltdownIsHappening) == 1;}set{Interlocked.Exchange(ref _meltdownIsHappening, Convert.ToInt64(value));}}
}

这效率,嘎嘎的高。

注意 Interlocked.Increment(ref this.counter); 在实现上,等同于lock(this.locker) this. Counter++;,不过效率吗,那是翻了几倍。可惜的是好东西总有限制。Interlocked仅仅支持整数类型。

4. Synchronized 同步操作

Synchronized 关键字,总有点像从哪里抄过来的,因此,这个用法并不常见。
不过它的含义倒是很清晰,就是同一时刻仅允许一个线程访问。

代码如下:

public class Test
{public volatile int foo = 0;[MethodImpl(MethodImplOptions.Synchronized)]public int Add(int a){return foo + a;}
}

MethodImpl(MethodImplOptions.Synchronized)这个属性的实现,也很简单,就是粗暴的lock(this)

因此,不建议直接使用。

在这里插入图片描述

总结

哦哦哦,好像意犹未尽,不过时间有限,先到此为止吧。

👓都看到这了,还在乎点个赞吗?

👓都点赞了,还在乎一个收藏吗?

👓都收藏了,还在乎一个评论吗?

这篇关于有关多线程环境下的Volatile、lock、Interlocked和Synchronized们的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/295670

相关文章

python常见环境管理工具超全解析

《python常见环境管理工具超全解析》在Python开发中,管理多个项目及其依赖项通常是一个挑战,下面:本文主要介绍python常见环境管理工具的相关资料,文中通过代码介绍的非常详细,需要的朋友... 目录1. conda2. pip3. uvuv 工具自动创建和管理环境的特点4. setup.py5.

Python中使用uv创建环境及原理举例详解

《Python中使用uv创建环境及原理举例详解》uv是Astral团队开发的高性能Python工具,整合包管理、虚拟环境、Python版本控制等功能,:本文主要介绍Python中使用uv创建环境及... 目录一、uv工具简介核心特点:二、安装uv1. 通过pip安装2. 通过脚本安装验证安装:配置镜像源(可

python获取cmd环境变量值的实现代码

《python获取cmd环境变量值的实现代码》:本文主要介绍在Python中获取命令行(cmd)环境变量的值,可以使用标准库中的os模块,需要的朋友可以参考下... 前言全局说明在执行py过程中,总要使用到系统环境变量一、说明1.1 环境:Windows 11 家庭版 24H2 26100.4061

pytest+allure环境搭建+自动化实践过程

《pytest+allure环境搭建+自动化实践过程》:本文主要介绍pytest+allure环境搭建+自动化实践过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、pytest下载安装1.1、安装pytest1.2、检测是否安装成功二、allure下载安装2.

VS配置好Qt环境之后但无法打开ui界面的问题解决

《VS配置好Qt环境之后但无法打开ui界面的问题解决》本文主要介绍了VS配置好Qt环境之后但无法打开ui界面的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目UKeLvb录找到Qt安装目录中designer.UKeLvBexe的路径找到vs中的解决方案资源

解决mysql插入数据锁等待超时报错:Lock wait timeout exceeded;try restarting transaction

《解决mysql插入数据锁等待超时报错:Lockwaittimeoutexceeded;tryrestartingtransaction》:本文主要介绍解决mysql插入数据锁等待超时报... 目录报错信息解决办法1、数据库中执行如下sql2、再到 INNODB_TRX 事务表中查看总结报错信息Lock

python多线程并发测试过程

《python多线程并发测试过程》:本文主要介绍python多线程并发测试过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、并发与并行?二、同步与异步的概念?三、线程与进程的区别?需求1:多线程执行不同任务需求2:多线程执行相同任务总结一、并发与并行?1、

SpringBoot实现多环境配置文件切换

《SpringBoot实现多环境配置文件切换》这篇文章主要为大家详细介绍了如何使用SpringBoot实现多环境配置文件切换功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 示例代码结构2. pom文件3. application文件4. application-dev文

Web技术与Nginx网站环境部署教程

《Web技术与Nginx网站环境部署教程》:本文主要介绍Web技术与Nginx网站环境部署教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Web基础1.域名系统DNS2.Hosts文件3.DNS4.域名注册二.网页与html1.网页概述2.HTML概述3.

Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题

《Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题》:本文主要介绍Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未... 目录一、前言二、系统架构检测三、卸载旧版 Go四、下载并安装正确版本五、配置环境变量六、验证安装七、常见