【多线程】volatile关键字详解

news/2025/3/6 0:14:38/文章来源:https://www.cnblogs.com/cmxb/p/18753983

volatile的作用

volatile主要用于解决可见性有序性的问题,但不保证原子性

  • 可见性:
    • 线程在操作变量时,会将主存中的变量拷贝一份到本地存储;修改有再找时机写回主存(不可控),这样多线程并发时会导致其他线程看到的数据和当前线程不一致
    • 使用volatile关键字修饰变量,可使得每次执行写操作时直接将值刷新到主存中,通过内存屏障使得其他线程本地副本失效;执行读操作时会强制从主存中加载最新的值。
  • 禁止指令重排序
    • JVM和CPU可能会对指令进行重排序优化(单例模式中如果静态变量不使用volatile关键字修饰会有重排序的风险)
    • volatile修饰的变量通过插入内存屏障来禁止编译器和处理器对指令进行重排序,来保证执行符合预期

适用场景

  • 状态标志位:如 volatile boolean flag,用于简单线程间通信。
  • 【设计模式】单例模式 的双重检查锁(Double-Checked Locking)。
  • 多线程环境下仅由一个线程写、其他线程读的变量,例如:【多线程】CopyOnWriteList。

volatile的写操作和读操作都是直接操作主存吗?

写操作:

执行写操作时,使用内存屏障将写入主存的变量在其他线程的副本状态置为失效,然后强制其他线程再要使用该变量时从主存中获取。

读操作:

读操作分两种情况

  • 线程在对volatile变量进行读取时,如果本地副本状态正常,则从本地缓存中读取该变量的值
    image

  • 线程在对volatile变量进行读取时,如果本地副本状态时失效,则从主存中读取该变量的值,刷新到本地缓存
    image

与synchronized的区别

  • synchronized用于实现原子性和互斥访问,同时隐含了可见性和有序性
    • 原子性:synchronized关键字通过锁机制保证同一时间只有一个线程执行临界区代码,保证原子性
    • 可见性和有序性:线程进入synchronized代码块时会从主存加载变量,写入本地内存;退出时会将本地内存刷新到主内存中;通过锁来保证代码块的代码不会被重排序到外部
  • 两者最大的区别
    • volatile修饰的变量所有的线程在变量发生变更后都会从主内存去取。
      synchronized代码块修改的变量(里面多线程共享的变量未被volatile修饰),只有进入synchronized代码的时候才会从主内存中取。
  • 所以多线程编程时如果对于某个变量是多线程的读和写,一定要加上volatile关键字修饰,否则未加锁的读线程可能会读到旧值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/894251.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WiFiGrab教程2:一键抓包5G并使用字典破解全流程

本文使用WiFiGrab抓取5G无线网络的握手包,实验对象为自己的路由器,并结合EWSA进行字典攻击,演示暴力破解的原理和全流程操作。WiFiGrab抓包5G 本文使用WiFiGrab抓取5G无线网络的握手包,实验对象为自己的路由器,并结合EWSA进行字典攻击,演示暴力破解的原理和全流程操作。软…

phylip 中利用NJ法构建进化树

001、测试文件vcf文件(base) [b20223040323@admin2 02_NJ_tree]$ ls outcome.vcf 002、格式转换;输入文件为vcf文件run_pipeline.pl -Xms1G -Xmx5G -importGuess outcome.vcf -ExportPlugin -saveAs sequences.phy -format Phylip_Inter ## 格式转换 003、

vue的深度学习

vue的深度学习 本次学习了vue脚手架的知识,使用的是选项api,初步分析 对于脚手架目录进行简单分析 src:用于存放源码,我们一般写代码的地方,其中的app.vue是根组件,components中存放其他组件,其他组件可以加到根组件下方 <template><div class="fullName"&g…

代码随想录算法训练营day23 | 39. 组合总和、40.组合总和II、131.分割回文串

组合总和点击查看代码 class Solution { public:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& candidates, int &target, int sum, int startIndex) {//由于for循环条件已经提前做了递归终止判断,故这里不用…

2023-3-5-ai试用

今天使用了ai来做简单的项目,这是我发给ai的话语这是相应的结构图,按照ai的回答做出,相应的依赖我们能够实现登录以及相应的查询,不过也有一些数据取不到,有一些bug,其他功能代码ai没有给出,需要我们进一步索要,不过也能看出ai是可以用于做项目了

车辆运维管理行业洞察与竞品分析

1. 前言 车辆运维管理是指对车辆进行日常维护、故障处理、性能监测、成本控制等一系列活动的管理。随着物联网、大数据、人工智能等技术的发展,车辆运维管理软件和解决方案的市场竞争日益激烈。 2. 确定目标通过产品差异化定位,找到竞争者的差异,打造自己的优势,抢占市场份…

go语言实现终端里的倒计时

最近在更新系统的时候发现pacman的命令行界面变了,我有很久没更新过设备上的Linux系统了,所以啥时候变的不好说。但这一变化成功勾起了我的好奇心。新版的更新进度界面如下:新的更新进度界面能同时显示多个进度条,而且并没有依靠ncurses这个传统的TUI库。为啥我能断定没有用…

备份是个好习惯

题目环境启动以后页面回显了一行字符串,丢进随波逐流里面以后发现解密不出来,如果有知道的大佬辛苦留言一下没啥思路,想到题目名字叫备份是个好习惯,说不定网页目录下真有bak文件,于是就拿御剑扫描一下扫完以后还真有打开以后就是这样一段代码点击查看代码 接下来就是代码…

使用 Net 处理 Excel 文件的时间列

前言最近,处理Excel的情况比较多,然后,就碰到了时间列,读取出来时中文,保存到数据库中着实麻烦,就找了下如何解决这个问题。正文1.这是读取Excel时候,调试的时候,时间列的格式,如下图:2.分享下原始读取Excel的公共方法,其实,也只能说这个方法写的有问题,所有列都按…

HTB Sherlock Easy Noted wp

靶场介绍:Simon, a developer working at Forela, notified the CERT team about a note that appeared on his desktop. The note claimed that his system had been compromised and that sensitive data from Simons workstation had been collected. The perpetrators per…

从Postman到Apipost:我的动态参数测试实战踩坑记

从Postman到Apipost:我的动态参数测试实战踩坑记作为全栈开发工程师,我最近在开发用户中心模块时遇到了一个棘手问题:如何高效测试包含复杂参数的API接口?我和团队小伙伴都习惯用Postman,直到这次让我们差点加班的"动态参数事件"... 第1次翻车:Postman的陷阱 记…