首页 > 其他 > 详细

对于Volatile型变量的特殊规则

时间:2021-02-16 17:58:11      阅读:19      评论:0      收藏:0      [点我收藏+]

1.关键字 volatile是Java虚拟机提供的最轻量级的同步机制

2.当一个变量被定义称volatile之后,它将具备两项特性:

1)保证此变量对所有线程可见性,这里的“可见性”是指当一条线程修改了这个变量的值,新值对于其他线程可以立即得知

 volatile变量在各个线程的工作内存中是不存在一致性问题的(从物理存储角度看,各个线程的工作内存中volatile变量也可以存在不一致的情况,但由于每次使用之前都要先刷新执行引擎看不到不一致的情况,因此可以认为不存在一致性问题),

但是JAVA里面的运算符操作并非原子操作,这导致volatile变量的运算在并发下一样的不安全

由于volatile变量只能保证可见性,在不符合一下两条规则的运算场景中,我们仍然需要通过枷锁(使用synchoronized、java.util.concurrent中的锁或原子类)来保证原子性

  •   运算结果并不依赖变量的当前值,或者能够保证只有单一的线程修改变量的值:这里不依赖指各自独立运算,不以当前变量为基础进行运算;要么单线程运算
  •   变量不需要与其他的状态变量共同参与不变约束

2)禁止指令重排

 

例如:B线程依赖于A线程的配置

Map configOptions;
char[] configText;
// 此变量必须定义为volatile
volatile boolean initialized = false;


// 假设以下代码在线程A中执行
// 模拟读取配置信息,当读取完成后,将initialized设置为true,通知其他线程配置可用
configOptions = new HashMap();
configText = readConfigFile(fileName);
processConfigOptions(configtext, configOptions);
initialized = true;

--------------------------------------------------------------------------
// 假设以下代码在线程B中执行
// 等待initialized 为true,代表线程A已经把配置信息初始化完成
while(!initialized) {
      sleep();          

}
// 使用线程A中初始化好的配置信息
doSomethingWithConfig();

如果定义 initialized变量时没有使用volatile修饰,就可能会由于指令重排序的优化,导致位于线程A中最后一条代码 “

initialized = true;”被提前执行,可能会放在代码块的第一行执行,这样在B线程使用配置信息的代码就可能出现错误

对于Volatile型变量的特殊规则

原文:https://www.cnblogs.com/kukufan/p/14406729.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!