当前位置: 首页 > news >正文

有关多线程环境下的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们

&#x1f4e2;欢迎点赞 &#xff1a;&#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0c;赐人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原创&#x1f4e2;作者格言&#xff1a;新的征程&#xff0c;我们面对的不仅…...

spring boot利用redis作为缓存

一、缓存介绍 在 Spring Boot 中&#xff0c;可以使用 Spring Cache abstraction 来实现缓存功能。Spring Cache abstraction 是 Spring 框架提供的一个抽象层&#xff0c;它对底层缓存实现&#xff08;如 Redis、Ehcache、Caffeine 等&#xff09;进行了封装&#xff0c;使得在…...

Android Studio 查看Framework源码

1、背景 安卓系统源码量很庞大&#xff0c;选择好的开发工具和方式去开发可以提升开发效率&#xff0c;常用的开发工具有Source Insight 、Visual Studio Code、Android Studio&#xff0c;vscode适合C和C代码开发&#xff0c;java层代码无法跳转和提示&#xff0c;因此&#…...

FileInputStream文件字节输入流

一.概念 以内存为基准&#xff0c;把磁盘文件中的数据以字节形式读入内存中 二.构造器 public FileInputStream(File file) public FileInputStream(String pathname) 这两个都是创建字节输入流管道与源文件接通 三.方法 public int read() :每次读取一个字节返回&#xff0c;如…...

【Qt】窗口和对话框区别、主窗口和二级窗口区别、QMainWindow和QDialog区别

窗口和对话框&#xff08;Window and Dialog Widgets&#xff09; 未嵌入在父界面中的界面称为窗口。&#xff08;通常&#xff0c;窗口具有边框和标题栏&#xff0c;尽管也可以使用合适的窗口标志创建没有此类标志的窗口&#xff09;。 在Qt中&#xff0c;QMainWindow和QDial…...

Python参数种类介绍

Python参数种类介绍 相比于一些其他编程语言&#xff0c;Python提供了更多的参数种类选项。这是Python的一大特点&#xff0c;使用不同的参数类型&#xff0c;可以提高函数的可读性和可维护性。例如&#xff0c;使用关键字参数可以使函数调用更加清晰&#xff0c;不需要记住参数…...

react事件机制

React 事件机制 React的事件机制是React框架中非常重要的一部分&#xff0c;用于处理用户交互和用户界面上的事件。React的事件机制在底层使用了虚拟DOM以及合成事件来提高性能和跨浏览器兼容性。以下是关于React事件机制的详细信息&#xff1a; 合成事件&#xff08;Syntheti…...

JAVA删除excel指定列

首先POI没有提供删除列的API&#xff0c;所以就需要用其他的方式实现。 在 java - Apache POI xls column Remove - Stack Overflow 这里找到了实现方式&#xff1a; 先将该列所有值都清空&#xff0c;然后将该列之后的所有列往前移动。 下面的工具类中 deleteColumns(Inpu…...

Netty编码器和解码器

文章目录 一、Decoder原理与实践1、ByteToMessageDecoder解码器2、自定义整数解码器1&#xff09;常规方式2&#xff09;ReplayingDecoder解码器 3、分包解码器3、MessageToMessageDecoder解码器 二、Netty内置的Decoder1、LineBasedFrameDecoder解码器2、DelimiterBasedFrameD…...

大语言模型(LLM)综述(三):大语言模型预训练的进展

A Survey of Large Language Models 前言4. PRE-TRAINING4.1数据收集4.1.1 数据源4.1.2 数据预处理4.1.3 预训练数据对LLM的影响 4.2 模型架构4.2.1 典型架构4.2.2 详细配置4.2.3 预训练任务4.2.4 解码策略4.2.5 总结和讨论 4.3 模型训练4.3.1 优化设置4.3.2 可扩展的训练技术 …...

如何在Node.js中使用环境变量或命令行参数来设置HTTP爬虫ip?

首先&#xff0c;定义问题&#xff1a;在 Node.js 应用程序中&#xff0c;我们可以通过环境变量或命令行参数来设置HTTP爬虫ip&#xff0c;以便在发送请求时使用这些HTTP爬虫ip。 亲身经验&#xff1a;我曾经需要为一个项目设置HTTP爬虫ip&#xff0c;以便在发送请求时使用这些…...

VMware打开共享虚拟机后找不到/mnt/hgfs/文件夹,以及不能拖拽/复制粘贴等操作,ubuntu不能安装VMware tools

问题原因 我的问题出现原因是&#xff0c;安装ubuntn虚拟机的时候VMware tools没有安装好&#xff0c;需要重新安装&#xff0c;但安装选项是暗的&#xff0c;不能操作。 类似这种情况&#xff0c;虚拟机开启时也是&#xff0c;因为我虚拟机已经装好了&#xff0c;开启时是亮…...

pytorch 入门 (五)案例三:乳腺癌识别识别-VGG16实现

本文为&#x1f517;小白入门Pytorch内部限免文章 &#x1f368; 本文为&#x1f517;小白入门Pytorch中的学习记录博客&#x1f366; 参考文章&#xff1a;【小白入门Pytorch】乳腺癌识别&#x1f356; 原作者&#xff1a;K同学啊 在本案例中&#xff0c;我将带大家探索一下深…...

【QT开发(14)】QT P2P chat 聊天

在【P2P学习&#xff08;2&#xff09;】P2P 通信&#xff0c;主要存在四种不同的网络模型的第一阶段&#xff1a;集中式P2P 模式 最简单的路由方式就是集中式&#xff0c;即存在一个中心节点保存了其他所有节点的索引信息&#xff0c;索引信息一般包括节点 IP 地址、端口、节…...

解决adb root命令时错误 adbd cannot run as root in production builds

我测试的手机是小米8&#xff0c;root权限已经刷过了&#xff0c;但是在pc端使用adb root命令的时候&#xff0c;会报错"adbd cannot run as root in production builds" 后来查资料发现是因为Magisk和安卓9版本的问题 https://www.cnblogs.com/jeason1997/p/124105…...

操作系统中套接字和设备独立性软件的关系

网络编程就是编写程序让两台联网的计算机相互交换数据。在我们不需要考虑物理连接的情况下&#xff0c;我们只需要考虑如何编写传输软件。操作系统提供了名为“套接字”&#xff0c;套接字是网络传输传输用的软件设备。 这是对软件设备的解释&#xff1a; 在操作系统中&#…...

C++ Qt/VTK装配体组成联动连接杆

效果 关键代码 #include "View3D.h" #include "Axis.h"#include <vtkActor.h> #include <vtkAppendPolyData.h > #include <vtkAreaPicker.h> #include <vtkAxesActor.h> #include <vtkBox.h> #include <vtkCamera.h>…...

File文件查找

用的是递归调用&#xff0c; &#xff08;递归死循环的结果是导致栈内存溢出错误&#xff09; 一.代码 package org.example;import java.io.File;public class day03 {public static void main(String[] args) {//文件查找&#xff0c;在d&#xff1a;temp下查找改名.mp4sea…...

小程序 wxml2canvas开发文档

wxml: <view class"share__canvas share__canvas1"><view class"share__canvas1-text draw_canvas" data-type"text" data-text"这是一段无边距文字">这是一段无边距文字</view> </view> <canvas canvas-…...

SpringCloud微服务 【实用篇】| 认识微服务

目录 一&#xff1a;认识微服务 1. 微服务框架介绍 2. 服务架构演变 3. 微服务技术对比 4. SpringCloud 图书推荐&#xff1a;《巧用ChatGPT快速提高职场晋升力》 一&#xff1a;认识微服务 本课程学习于黑马&#xff0c;会通过分层次学习&#xff0c;分为三部分去讲解微…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...