//x、y为非volatile变量//flag为volatile变量 x = 2;//语句1y = 0;//语句2flag = true;//语句3x = 4;//语句4y = -1;//语句5
由于flag变量为volatile变量,那么在进行指令重排序的过程的时候,不会将语句3放到语句1、语句2前面,也不会讲语句3放到语句4、语句5后面 。但是要注意语句1和语句2的顺序、语句4和语句5的顺序是不作任何保证的 。
并且volatile关键字能保证,执行到语句3时,语句1和语句2必定是执行完毕了的,且语句1和语句2的执行结果对语句3、语句4、语句5是可见的 。
那么我们回到前面举的一个例子:
//线程1:context = loadContext();//语句1inited = true;//语句2 //线程2:while(!inited ){sleep()}doSomethingwithconfig(context);
前面举这个例子的时候,提到有可能语句2会在语句1之前执行,那么久可能导致context还没被初始化,而线程2中就使用未初始化的context去进行操作,导致程序出错 。
这里如果用volatile关键字对inited变量进行修饰,就不会出现这种问题了,因为当执行到语句2时,必定能保证context已经初始化完毕 。
④ volatile的原理和实现机制
前面讲述了源于volatile关键字的一些使用,下面我们来探讨一下volatile到底如何保证可见性和禁止指令重排序的 。
下面这段话摘自《深入理解Java虚拟机》:
“观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令”
lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:
1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
2)它会强制将对缓存的修改操作立即写入主存;
3)如果是写操作,它会导致其他CPU中对应的缓存行无效 。
5、使用volatile关键字的场景synchronized关键字是防止多个线程同时执行一段代码,那么就会很影响程序执行效率,而volatile关键字在某些情况下性能要优于synchronized,但是要注意volatile关键字是无法替代synchronized关键字的,因为volatile关键字无法保证操作的原子性 。通常来说,使用volatile必须具备以下2个条件:
1)对变量的写操作不依赖于当前值
2)该变量没有包含在具有其他变量的不变式中
实际上,这些条件表明,可以被写入 volatile 变量的这些有效值独立于任何程序的状态,包括变量的当前状态 。
事实上,我的理解就是上面的2个条件需要保证操作是原子性操作,才能保证使用volatile关键字的程序在并发时能够正确执行 。
下面列举几个Java中使用volatile的几个场景 。
① 状态标记量
volatile boolean flag = false; while(!flag){doSomething();} public void setFlag() {flag = true;}
volatile boolean inited = false;//线程1:context = loadContext();inited = true;//线程2:while(!inited ){sleep()}doSomethingwithconfig(context);
② double check
class Singleton{private volatile static Singleton instance = null;private Singleton() {}public static Singleton getInstance() {if(instance==null) {synchronized (Singleton.class) {if(instance==null)instance = new Singleton();}}return instance;}}
欢迎小伙伴们留言交流~
推荐阅读
- Java正则表达式详解
- Jackson注解详解
- 华硕主板后缀字母代表什么含义?华硕主板型号命名规则与系列详解
- 决明子菊花茶详解,决明子菊花茶的做法
- Apollo配置中心管理后台的详解
- 开发者手撸类谷歌搜索关键字智能匹配功能系统
- 教你紫砂壶的保养方法,详解紫砂壶冲泡普洱茶的方法
- 一文详解,PHP 协程:Go + Chan + Defer
- Serverless无服务器架构详解
- Docker---Dockerfile 详解