前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Volatile 关键字

Volatile 关键字

作者头像
赵哥窟
发布2022-06-01 10:13:52
2340
发布2022-06-01 10:13:52
举报
文章被收录于专栏:日常技术分享日常技术分享

最近,在一篇文章中了解到了 volatile 关键字,查阅了一些相关资料进行了学习,并将学习笔记记录如下,希望能给小伙伴们带来一些帮助。如果文章内容存在一些错误,也请小伙伴们指正,感谢。

volatile 的作用

大家都应该知道 volatile 的主要作用有两点: 1、 保证变量的内存可见性 。 2、禁止指令重排序。

内存可见性

那么什么是内存可见性呢? 内存可见性是指当一个线程修改了某个变量的值,其它线程总是能知道这个变量变化。也就是说,如果线程 A 修改了共享变量 i 的值,那么线程 B 在使用 i 的值时,能立即读到 i的最新值。

可见性问题的解决方案 我们如何保证多线程下共享变量的可见性呢?也就是当一个线程修改了某个值后,对其他线程是可见的。

这里有两种方案:加锁 和 使用 volatile 关键字。

禁止指令重排序

什么是重排序?

计算机在执行程序时,为了提高性能,编译器和处理器常常会对指令重排,一般分为以下三种

1、编译器优化重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。 2、指令级并行重排序。现代处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。 3、内存系统重排序。由于处理器使用缓存和读 / 写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。

image.png

为了更好地理解重排序,请看下面的部分示例代码:

代码语言:javascript
复制
public void mySort() {
    int x = 11;
    int y = 12;
    x = x + 5;
    y = x * x;
}

按照正常单线程环境,执行顺序是 1 2 3 4

但是在多线程环境下,可能出现以下的顺序: 2 1 3 4 1 3 2 4 上述的过程就可以当做是指令的重排,即内部执行顺序,和我们的代码顺序不一样但是指令重排也是有限制的,即不会出现下面的顺序 4 3 2 1 因为处理器在进行重排时候,必须考虑到指令之间的数据依赖性.因为步骤 4:需要依赖于 y的申明,以及x的申明,故因为存在数据依赖,无法首先执行.

Volatile针对指令重排做了啥

Volatile实现禁止指令重排优化,从而避免了多线程环境下程序出现乱序执行的现象.

首先了解一个概念,内存屏障(Memory Barrier)又称内存栅栏,是一个CPU指令,它的作用有两个:

1、保证特定操作的顺序 2、保证某些变量的内存可见性(利用该特性实现volatile的内存可见性)

由于编译器和处理器都能执行指令重排的优化,如果在指令间插入一条Memory Barrier则会告诉编译器和CPU,不管什么指令都不能和这条Memory Barrier指令重排序,也就是说 通过插入内存屏障禁止在内存屏障前后的指令执行重排序优化。 内存屏障另外一个作用是刷新出各种CPU的缓存数,因此任何CPU上的线程都能读取到这些数据的最新版本。 也就是过在Volatile的写 和 读的时候,加入屏障,防止出现指令重排的

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-06-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • volatile 的作用
  • 内存可见性
  • 禁止指令重排序
  • Volatile针对指令重排做了啥
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档