网站首页 > 资源文章 正文
本篇文章从happens-before定义、用途以及具体规则三个方面对happens-before进行解读,并通过源码案例深入了解为什么需要happens-before规则和什么是指令重排序。
什么是happens-before
happens-before: A happens-before B就是A先行发生于B(这种说法不是很准确),定义为hb(A, B)。在Java内存模型中,happens-before的意思是前一个操作的结果可以被后续操作获取。
为什么需要happens-before
JVM会对代码进行编译优化,会出现指令重排序情况,为了避免编译优化对并发编程安全性的影响,需要happens-before规则定义一些禁止编译优化的场景,保证并发编程的正确性。以双重检查单例示例进行分析:
/**
* 懒汉式 双重检查锁实现单例
*/
public class LazyDoubleCheckSingleton {
private static LazyDoubleCheckSingleton instance = null;
private LazyDoubleCheckSingleton(){}
/**
* 双重检查锁 减小加锁粒度 相对于LazySynchronizedSingleton提升性能 减少不必要的锁开销
* @return
*/
public static LazyDoubleCheckSingleton getInstance(){
if (instance == null){
synchronized (LazyDoubleCheckSingleton.class){
if (instance == null){
//CPU执行时候会转换成JVM指令执行
//1.分配内存给对象 2.初始化对象 3.将初始化对象和内存地址建立关联,赋值
//4.用户初次访问
//存在问题指令重排序 有可能2 3顺序颠倒
instance = new LazyDoubleCheckSingleton();
}
}
}
return instance;
}
}
上述代码中instance = new LazyDoubleCheckSingleton()并不是原子操作 ,JVM会分解成以下几个命令执行:
- 给对象分配内容
- 初始化对象
- 将初始化对象和内存地址建立关联
按照上面的分解顺序(1->2->3)执行不存在任何问题,但是由于JVM编译优化的存在,可能导致2和3步骤颠倒,即按1->3->2顺序执行(这就是指令重排序)。按照1->3->2顺序执行,在多线程环境中执行getInstance就有可能出现instance已经和初始对象内存建立关联,但是对象还没有初始化完成的情况,即执行if (instance == null)的时候instance != null 直接返回没有初始化完成的instance,导致再使用instance实例的时候报错。volatile关键字是可以解决指令重排序问题的一种方式,具体解决方式如下:
//添加volatile解决指令重排序问题
private volatile static LazyDoubleCheckSingleton instance = null;
有哪些happens-before规则
END
笔者是一位热爱互联网、热爱互联网技术、热于分享的年轻人,如果您跟我一样,我愿意成为您的朋友,分享每一个有价值的知识给您。喜欢作者的同学,点赞+转发+关注哦!
点赞+转发+关注,私信作者“读书笔记”即可获得BAT大厂面试资料、高级架构师VIP视频课程等高质量技术资料。
猜你喜欢
- 2024-11-08 “过期食品”英文怎么说?(过期食物用英语怎么说)
- 2024-11-08 Before it's too late 可以翻译成“来不及了”吗
- 2024-11-08 before和until主从句中的使用和区别
- 2024-11-08 一课译词:似曾相识(似曾相识的解释意思)
- 2024-11-08 一课译词:小巫见大巫(小巫见大巫是哪几个字)
- 2024-11-08 每天一个小知识,今天咱们讲,公元、世纪、年代
- 2024-11-08 一课译词:开夜车(开夜车的几大恐怖禁忌与灵异事件)
- 2024-11-08 after、before、at first 及first的用法?一看就会
- 2024-11-08 prior to和before的区别(prior to 和previous to)
- 2024-11-08 12. 介词before 的用法(before作为介词的用法)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- 电脑显示器花屏 (79)
- 403 forbidden (65)
- linux怎么查看系统版本 (54)
- 补码运算 (63)
- 缓存服务器 (61)
- 定时重启 (59)
- plsql developer (73)
- 对话框打开时命令无法执行 (61)
- excel数据透视表 (72)
- oracle认证 (56)
- 网页不能复制 (84)
- photoshop外挂滤镜 (58)
- 网页无法复制粘贴 (55)
- vmware workstation 7 1 3 (78)
- jdk 64位下载 (65)
- phpstudy 2013 (66)
- 卡通形象生成 (55)
- psd模板免费下载 (67)
- shift (58)
- localhost打不开 (58)
- 检测代理服务器设置 (55)
- frequency (66)
- indesign教程 (55)
- 运行命令大全 (61)
- ping exe (64)
本文暂时没有评论,来添加一个吧(●'◡'●)