当前位置:网站首页>volatile关键字及其作用
volatile关键字及其作用
2022-07-27 01:32:00 【tea-Sir】
本文主要介绍Java语言中的volatile关键字,内容涵盖volatile的保证内存可见性、禁止指令重排等。
1 保证内存可见性
1.1 基本概念
可见性是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。也就是一个线程修改的结果,另一个线程马上就能看到。
1.2 实现原理
当对非volatile变量进行读写的时候,每个线程先从主内存拷贝变量到CPU缓存中,如果计算机有多个CPU,每个线程可能在不同的CPU上被处理,这意味着每个线程可以拷贝到不同的CPU cache中。
volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,保证了每次读写变量都从主内存中读,跳过CPU cache这一步。当一个线程修改了这个变量的值,新值对于其他线程是立即得知的。
2 禁止指令重排
2.1 基本概念
指令重排序是JVM为了优化指令、提高程序运行效率,在不影响单线程程序执行结果的前提下,尽可能地提高并行度。指令重排序包括编译器重排序和运行时重排序。
latile变量禁止指令重排序。针对volatile修饰的变量,在读写操作指令前后会插入内存屏障,指令重排序时不能把后面的指令重排序到内存屏
示例说明:
double r = 2.1; //(1)
double pi = 3.14;//(2)
double area = pi*r*r;//(3)
虽然代码语句的定义顺序为1->2->3,但是计算顺序1->2->3与2->1->3对结果并无影响,所以编译时和运行时可以根据需要对1、2语句进行重排序。
2.2 指令重排带来的问题
如果一个操作不是原子的,就会给JVM留下重排的机会。
线程A中
{
context = loadContext();
inited = true;
}
线程B中
{
if (inited)
fun(context);
}
如果线程A中的指令发生了重排序,那么B中很可能就会拿到一个尚未初始化或尚未初始化完成的context,从而引发程序错误。
2.3 禁止指令重排的原理
volatile关键字提供内存屏障的方式来防止指令被重排,编译器在生成字节码文件时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。
JVM内存屏障插入策略:
每个volatile写操作的前面插入一个StoreStore屏障;
在每个volatile写操作的后面插入一个StoreLoad屏障;
在每个volatile读操作的后面插入一个LoadLoad屏障;
在每个volatile读操作的后面插入一个LoadStore屏障。
2.4 指令重排在双重锁定单例模式中的影响
基于双重检验的单例模式(懒汉型)
public class Singleton3 {
private static Singleton3 instance = null;
private Singleton3() {}
public static Singleton3 getInstance() {
if (instance == null) {
synchronized(Singleton3.class) {
if (instance == null)
instance = new Singleton3();// 非原子操作
}
}
return instance;
}
}
instance= new Singleton()并不是一个原子操作,其实际上可以抽象为下面几条JVM指令:
memory =allocate(); //1:分配对象的内存空间
ctorInstance(memory); //2:初始化对象
instance =memory; //3:设置instance指向刚分配的内存地址
上面操作2依赖于操作1,但是操作3并不依赖于操作2。所以JVM是可以针对它们进行指令的优化重排序的,经过重排序后如下:
memory =allocate(); //1:分配对象的内存空间
instance =memory; //3:instance指向刚分配的内存地址,此时对象还未初始化
ctorInstance(memory); //2:初始化对象
指令重排之后,instance指向分配好的内存放在了前面,而这段内存的初始化被排在了后面。在线程A执行这段赋值语句,在初始化分配对象之前就已经将其赋值给instance引用,恰好另一个线程进入方法判断instance引用不为null,然后就将其返回使用,导致出错。
解决办法
用volatile关键字修饰instance变量,使得instance在读、写操作前后都会插入内存屏障,避免重排序。
public class Singleton3 {
private static volatile Singleton3 instance = null;
private Singleton3() {}
public static Singleton3 getInstance() {
if (instance == null) {
synchronized(Singleton3.class) {
if (instance == null)
instance = new Singleton3();
}
}
return instance;
}
}
3 volatile无法保证原子性
由于num++非原子操作,先获取num的值,然后写回新的num,最后新值num++;
A线程和B线程可能同时取了一个相同的值,导致线程不安全。
解决方法:给方法增加一个synchronized关键字,但加synchronized就不需要volatile了。
/** * @description:volatile非原子性测试 * @author: teasir * @create: 2022/07/22 **/
public class VolatileVisibility {
private volatile int num;
public int inscrease(){
return num++;
}
}
4 适用场景
(1)volatile是轻量级同步机制。在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,是一种比synchronized关键字更轻量级的同步机制。
(2)volatile无法同时保证内存可见性和原子性。加锁机制既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性。
(3)volatile不能修饰写入操作依赖当前值的变量。声明为volatile的简单变量如果当前值与该变量以前的值相关,那么volatile关键字不起作用,也就是说如下的表达式都不是原子操作:“count++”、“count = count+1”。
(4)当要访问的变量已在synchronized代码块中,或者为常量时,没必要使用volatile;
(5)volatile屏蔽掉了JVM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。
边栏推荐
- Worth more than 100 million! The 86 version of "red boy" refuses to be a Daocheng Xueba. He is already a doctor of the Chinese Academy of Sciences and has 52 companies under his name
- Worthington果胶酶的特性及测定方案
- C语言const用法详解
- Hcip day 14 notes
- Best practices of opentelemetry in service grid architecture
- 一个测试类了解BeanUtils.copyProperties
- 注解@Autowired和@Resource的区别总结
- 图解 SQL,这也太形象了吧!
- Baidu cloud face recognition
- 5、 MFC view windows and documents
猜你喜欢

spark学习笔记(四)——sparkcore核心编程-RDD
![Analysis of [paper] pointlanenet papers](/img/f6/8001be4f90fe15100e0295de02491f.png)
Analysis of [paper] pointlanenet papers

身家破亿!86版「红孩儿」拒绝出道成学霸,已是中科院博士,名下52家公司

30分钟彻底弄懂 synchronized 锁升级过程

Hcip 13th day notes

How to use devaxpress WPF to create the first MVVM application in winui?

Jmeter分布式压测

spark:地区广告点击量排行统计(小案例)

Zhang Ping, Alibaba cloud Solution Architect: system construction of cloud native digital safety production

Annotation summary of differences between @autowired and @resource
随机推荐
The most complete basic knowledge of software testing in the whole network (a must for beginners)
Alibaba cloud technology expert Yang Zeqiang: Construction of observability on elastic computing cloud
“date: write error: No space left on device”解决
[binary search simple question] leetcode 35. search insertion position, 69. Square root of X, 367. Effective complete square, 441. Arrange coins
再学RecyclerView的回收复用机制
Role of thread.sleep (0)
Best practices of opentelemetry in service grid architecture
深入理解Mysql索引底层数据结构与算法
Analysis of [paper] pointlanenet papers
Comprehensive care analysis lyriq Ruige battery safety design
图解 SQL,这也太形象了吧!
[paper]PointLaneNet论文浅析
队列达到最大长度代码实战
Annotation summary of differences between @autowired and @resource
Social wechat applet of fanzhihu forum community
AcWing 2074. 倒计数 模拟
一体式水利视频监控站 遥测终端视频图像水位水质水量流速监测
水仙花数(DAY 78)
渗透测试-后渗透-痕迹清理
IDEA 连接数据库查询数据后控制台表头中文乱码的解决方法