正确理解volatile与happens-before
1. 双重校验锁实现单例的问题
在延迟实现单例时,一般代码形式如下:
public class Foo {
private static volatile Foo instance; public static Foo getInstance() {
//第一次检查,不锁定
if (null == instance) {
//一旦初始化,第一次检查将无法通过,不会有锁定开销
synchronized (Foo.class) {
//第二次检查,锁定
if (null == instance) {
instance = new Foo();
}
}
}
return instance;
}
}
看起来很简单,但这里有个容易忽略的点,就是instance变量,需要用volatile修饰。
为什么?如果不加的话会有什么问题呢?
让我们把目光聚焦到第11行,初始化instance变量。这一行代码可以分解为如下3行伪代码。
memory = allocate(); //1. 分配对象的内存空间 ctorInstance(memory);//2. 初始化对象 instance = memory; //3.设置instance指向刚分配的内存地址
上面伪代码中的2和3,是可能会被重排序的,重排序后将变成如下时序:
memory = allocate(); //1. 分配对象的内存空间 instance = memory; //3.设置instance指向刚分配的内存地址,注意,此时对象未初始化。 ctorInstance(memory);//2. 初始化对象
那么在多线程并发的场景下,假设有两条线程AB同时访问这个方法,可能发生以下的访问顺序:
时间 线程A 线程B
1 分配内存空间(对应1)
2 设置instance指向内存空间(对应3)
3 判断instance是否为null
4 由于instance不为null, 不再等待进行临界区,直接访问instance引用的对象
5 初始化对象(对应2)
这样一来,B在访问instance变量时,可能由于instance未初始化而导致出现一些异常。
那么,为什么加上volatile修饰就可以避免这种情况呢?这就涉及到happens-before和volatile的语义了。
2.happens-before与volatile语义
从JDK5开始,Java使用新的JSR-133内存模型。JSR-133使用happens-before的概念来阐述操作之间的内存可见性。在JMM中,如果一个操作执行的结果需要对另一个操作可见,以这两个操作之间必须要有happens-before关系。这里提到的两个操作,既可以是在一个线程之内,也可以是在不同的线程之间。
与程序员密切相关的happens-before规则如下。
1)程序顺序规则:一个线程中的每个操作,happens-before于该线程的任意后续操作。
2)监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。
3)volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读。
4)传递性:如果A happens-before B,B happens-before C,那么A happens-before C.
理解volatile特性的一个好方法是把对volatile变量的单个读/写,看成是使用同一个锁对这些单个读/写操作做了同步。也就是说,对任意单个volatile变化的读/写具有原子性,但类似于volatile++这种复合操作不具有原子性。
那么上面第三条规则是怎么实现的呢?请参考:深入理解Java内存模型(四)——volatile
简单来说,就是在volatile写之后加入了一个StoreLoad屏障,防止后面的读与前面的写重排序了。这样后面的线程读到的,就是一个完整的对象。
参考:《Java并发编程的艺术》
正确理解volatile与happens-before的更多相关文章
- 理解volatile
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- Java并发专题(三)深入理解volatile关键字
前言 上一章节简单介绍了线程安全以及最基础的保证线程安全的方法,建议大家手敲代码去体会.这一章会提到volatile关键字,虽然看起来很简单,但是想彻底搞清楚需要具备JMM.CPU缓存模型的知识.不要 ...
- 5.彻底理解volatile
1. volatile简介 在上一篇文章中我们深入理解了java关键字synchronized,我们知道在java中还有一大神器就是关键volatile,可以说是和synchronized各领风骚,其 ...
- 彻底理解volatile,领悟其中奥妙
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- 让你彻底理解volatile,面试不再愁
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- 深入理解volatile关键字
Java内存模型 想要理解volatile为什么能确保可见性,就要先理解Java中的内存模型是什么样的. Java内存模型规定了所有的变量都存储在主内存中.每条线程中还有自己的工作内存,线程的工作内存 ...
- 对精致码农大佬的 [理解 volatile 关键字] 文章结论的思考和寻找真相
一:背景 1. 讲故事 昨天在园里的编辑头条看到 精致码农大佬 写的一篇题为:[C#.NET 拾遗补漏]10:理解 volatile 关键字 (https://www.cnblogs.com/will ...
- 彻底理解volatile关键字
1. volatile简介 在上一篇文章中我们深入理解了java关键字,我们知道在java中还有一大神器就是关键volatile,可以说是和synchronized各领风骚,其中奥妙,我们来共同探讨下 ...
- java并发编程(五)正确使用volatile
转载请注明出处: volatile用处说明 在JDK1.2之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的.而随着JVM的成熟和优化,现在在多线程 ...
随机推荐
- libvirt- Virsh 所有命令详单
help 打印帮助 attach-device 从一个XML文件附加装置 attach-disk 附加磁盘设备 attach-interface 获 ...
- vs2010 安装 Ajax Control Toolkit
Ajax Control Toolkit 7.1005.0 The Ajax Control Toolkit contains a rich set of controls that you can ...
- GeoServer之sqlserver插件使用
GeoServer之sqlserver插件使用 安装好sqlserver插件后,点击出现的第一个选项,开始创建wms服务. 输入参数: 工作区:为geoserver中创建的工作区 数据源名称:自定义 ...
- leetcode697
public class Solution { public int FindShortestSubArray(int[] nums) { //先找到最大频度的数字都有哪些,加入到一个集合中 var ...
- exited with code 1
brcc32 command line for "Project1.vrc" c:\program files\embarcadero\rad studio\9.0\bin\c ...
- 跟我学算法-tensorflow 实现线性拟合
TensorFlow™ 是一个开放源代码软件库,用于进行高性能数值计算.借助其灵活的架构,用户可以轻松地将计算工作部署到多种平台(CPU.GPU.TPU)和设备(桌面设备.服务器集群.移动设备.边缘设 ...
- Hibernate面试问题集锦: 概述
ImportNew注: 本文是ImportNew编译整理的Java面试题系列文章之一.你可以从这里查看全部的Java面试系列. Q.怎么配置Hibernate? A.Configuration类使用配 ...
- 读取resource下文件
ArrayList<PatrolOper> patrolOpers = new ArrayList<>(); String jsonData = null; File json ...
- easyui datagrid combobox下拉框获取数据问题
最近在使用easyui的datagrid,在可编辑表格中添加一个下拉框,查了下API,可以设置type : 'combobox',来做下拉框,这下拉框是有了,可是这后台数据怎么传过来呢,通过查API可 ...
- iOS设计模式(01):观察者
iOS设计模式(01):观察者 iOS-Observer-Pattern 什么是观察者模式 什么是观察者模式?你曾经订阅过报纸吗?在订阅报纸的时候,你不用去任何地方,只需要将你的个人地址信息以及订阅信 ...