volatile 关键字的作用(变量可见性、禁止重排序)

volatile 关键字的作用(变量可见性、禁止重排序)

Java 语言提供了一种稍弱的同步机制,即 volatile 变量,用来确保将变量的更新操作通知到其他线程。volatile 变量具备两种特性,volatile 变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取 volatile 类型的变量时总会返回最新写入的值。

变量可见性

其一是保证该变量对所有线程可见,这里的可见性指的是当一个线程修改了变量的值,那么新的值对于其他线程是可以立即获取的。

解决内存可见性问题方式的一种是加锁,但是使用锁太笨重,因为它会带来线程上下文的切换开销。Java提供了一种弱形式的同步,也就是volatile关键字。该关键字确保对一个变量的更新对其他线程马上可见。

当一个变量被声明为volatile时,线程在写入变量时不会把值缓存在寄存器或者其他地方,而是会把值刷新回主内存。

当其他线程读取该共享变量时,会从主内存重新获取最新值,而不是使用当前线程的工作内存中的值。

理解volatile保证可见性的一个好方法是把对volatile变量的单个读/写,看成是使用同一个锁对这些单个读/写操作做了同步。示例如下:

public class VolatileDemo {volatile long count = 0L;public void set(long l) {count = l;}public void getAndIncrement() {count++;}public long get() {return count;}}class VolatileDemo2 {long count = 0L;public synchronized void set(long l) {count = l;}public void getAndIncrement() {long temp = get();temp += 1L;set(temp);}public synchronized long get() {return count;}}
禁止重排序

volatile 禁止了指令重排。

sychronized 更轻量级的同步锁

在访问 volatile 变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此 volatile 变量是一种比 sychronized 关键字更轻量级的同步机制。volatile 适合这种场景:一个变量被多个线程共享,线程直接给这个变量赋值。

image-20231211202536195

当对非 volatile 变量进行读写的时候,每个线程先从内存拷贝变量到 CPU 缓存中。如果计算机有多个 CPU,每个线程可能在不同的 CPU 上被处理,这意味着每个线程可以拷贝到不同的 CPU cache 中。而声明变量是 volatile 的,JVM 保证了每次读变量都从内存中读,跳过 CPU cache 这一步。

适用场景

值得说明的是对 volatile 变量的单次读/写操作可以保证原子性的,如 long 和 double 类型变量,但是并不能保证 i++这种操作的原子性,因为本质上 i++是读、写两次操作。在某些场景下可以代替 Synchronized。但是,volatile 的不能完全取代 Synchronized 的位置,只有在一些特殊的场景下,才能适用 volatile。总的来说,必须同时满足下面两个条件才能保证在并发环境的线程安全:

(1)对变量的写操作不依赖于当前值(比如 i++),或者说是单纯的变量赋值(boolean flag = true)。

(2)该变量没有包含在具有其他变量的不变式中,也就是说,不同的 volatile 变量之间,不能互相依赖。只有在状态真正独立于程序内其他内容时才能使用 volatile。

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

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

相关文章

在做题中学习(31):电话号码的字母组合(全排列)

17. 电话号码的字母组合 - 力扣(LeetCode) 思路:既然要排列组合,就得先根据数字字符取出来 所以先定义一个string类的数组通过下标取到每个数字对应的映射。 string _numsTostr[10]{"","","abc"…

12.11 C++ 作业

完善对话框,点击登录对话框,如果账号和密码匹配,则弹出信息对话框,给出提示”登录成功“,提供一个Ok按钮,用户点击Ok后,关闭登录界面,跳转到其他界面 如果账号和密码不匹配&#xf…

如何在Word中简洁地插入代码

如何在Word中简洁地插入代码 背景: ​ 最近在一写一些论文或者报告的时候,需要将源代码放在论文的最后,有一个很头疼的问题,如果直接把代码从编辑器复制到word中,就变成了下面这个样子: 这有点丑陋啊&…

jemeter,同一线程组内,调用cookie实现接口关联

取cookie方式参考上一篇:jemeter,取“临时重定向的登录接口”响应头中的cookie-CSDN博客 元件结构 登录后要执行的接口为“api/get_event_list/”,在该HTTP请求下创建HTTP信息头管理器,配置如下: 执行测试后&#xff0…

Elasticsearch,Kibana集成,x-pack鉴权配置

Elasticsearch,Kibana集成 Java8环境部署[CentOS7] cd /usr/local/src wget https://repo.huaweicloud.com/java/jdk/8u201-b09/jdk-8u201-linux-x64.tar.gztar -xzvf jdk-8u201-linux-x64.tar.gz -C /usr/local#配置环境变量 vim /etc/profile #文末添加 export JAVA_HOME/us…

轻空间助力中国高校实现场馆多功能一体化

中国高校在迎接体育、文艺、学术等多元化需求的同时,面临着场馆设施不足、建设成本高的难题。然而,随着轻空间(江苏)膜科技有限公司的崭新解决方案的引入,中国高校如苏州大学等正迎来一场场馆多功能一体化的革命。 创新…

某信服 EDR 白程序DLL劫持

本文用到的白程序回复公众号20231211进行获取。 嗯… 记得去年HW的时候某信服给我装的EDR一直没卸载,不是不想卸载,是因为卸载要密码,所以就摆烂了。。。。 找到EDR这个目录,然后把目录复制到虚拟机中,然后一个一个e…

C++ Qt开发:PushButton按钮组件

Qt 是一个跨平台C图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍QPushButton按钮组件的常用方法及灵活运用。 …

为什么推荐将静态资源放到CDN上?

一、什么是静态资源 说到静态资源,我们还要知道什么是动态资源 静态资源 静态资源是指在服务器上存储的不经常改变的文件,如图片、CSS 文件、JavaScript 文件、字体文件等。与之相对的是动态资源,动态资源是根据用户请求和服务器端处理生成的…

视频中自监督学习:「我的世界」下指令理解与跟随

本文介绍了北京大学人工智能研究院梁一韬助理教授所带领的 CraftJarvis 团队在「我的世界」环境下探索通用智能体设计的新进展,题为“GROOT: Learning to Follow Instructions by Watching Gameplay Videos”。 ​ GROOT 该研究的核心目标是探索能否摆脱文本数据的标…

图形化编程:一种全新的编程方式

在当今数字化世界中,编程已经成为一项重要的技能,而图形化编程则是一种全新的编程方式,它通过图形化的界面和拖拽式的操作方式,让编程变得更加直观、简单和有趣。6547网将介绍图形化编程的概念、特点以及在教育、游戏开发等领域的…

cobalt_strike_4.7启动报错.teamserver: 行 6: .TeamServerImage: 权限不够(解决方法)

cobalt_strike_4.7启动报错.teamserver: 行 6: .TeamServerImage: 权限不够(解决方法) 是TeamServerImage文件没有执行权限,不是teamserver这个文件。哎~ ​​