Java-内存模型 final 和 volatile 的内存语义
前提:内存屏障
内存屏障(Memory Barrier)与内存栅栏(Memory Fence)是同一个概念。
用于阻止指令重排序。保证了特定操作的执行顺序和某些变量的内存可见性。
JMM 内存屏障分为四类:
- Store:将处理器缓存的数据刷新到内存中。
- Load:将内存存储的数据拷贝到处理器的缓存中。
屏障类型 | 指令示例 | 说明 |
---|---|---|
LoadLoad | Load1;LoadLoad;Load2 | 该屏障确保 Load1 数据的装载先于 Load2 及其后所有装载指令的操作 |
StoreStore | Store1;StoreStore;Store2 | 该屏障确保 Store1 立刻刷新数据到内存(使其对其他处理器可见)的操作先于 Store2 及其后所有存储指令的操作 |
LoadStore | Load1;LoadStore;Store2 | 确保 Load1 的数据装载先于 Store2 及其后所有的存储指令刷新数据到内存的操作 |
StoreLoad | Store1;StoreLoad;Load2 | 该屏障确保 Store1 立刻刷新数据到内存的操作先于 Load2 及其后所有装载装载指令的操作。它会使该屏障之前的所有内存访问指令(存储指令和访问指令)完成之后,才执行该屏障之后的内存访问指令 |
StoreLoad Barriers 同时具备其他三个屏障的效果,是目前大多数 CPU 所支持的。但是相对其他屏障,该屏障的开销相对昂贵。
一、final
https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.5
声明一个 final 成员时,必须在构造函数退出前设置它的值。
class FinalFieldExample {
final int x; public FinalFieldExample() {
x = 3;
可见性
final 修饰的变量作为不可变变量,只要对象是正确构造的(没有 this 逃逸发生),不需要任何同步措施就可以保证任何线程都能读到变量在构造函数中被初始化之后的值。
关于this逃逸:
https://www.jianshu.com/p/49068f29a460
https://www.hollischuang.com/archives/2583
有序性
final 写:“构造函数内对一个 final 域的写入”,与, “随后把这个被构造对象的引用赋值给一个引用变量”,这两个操作之间不能重排序。
final 读:“初次读一个包含 final 域的对象的引用” ,与, “随后初次读对象的 final 域”,这两个操作之间不能重排序(先赋值,再调用)。
二、volatile
原子性
32 位的 JDK 中 volatile 修饰后的 long 和 double 也具有原子性。但是 volatile int i = 0;i++; 就不具备原子性,因此可以理解为对单次 volatile 变量的读写操作具有原子性,复合操作(如 i++)不具有原子性。
可见性
编译器会为 volatile 修饰的变量的读写操插入内存屏障,被 volatile 修饰的变量在被修改后可以立即同步到主内存,被其修饰的变量在每次是用之前都从主内存刷新。
有序性
CPU 可能对输入代码进行乱序执行,比如 load->add->save 有可能被优化成 load->save->add。内存屏障同样可以来限制处理器对指令进行重排序。
https://www.hollischuang.com/archives/2673
https://www.jianshu.com/p/aa432a918db9
https://www.jianshu.com/p/157279e6efdb
Java-内存模型 final 和 volatile 的内存语义的更多相关文章
- 全面理解Java内存模型(JMM)及volatile关键字(转载)
关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoad ...
- 全面理解Java内存模型(JMM)及volatile关键字(转)
原文地址:全面理解Java内存模型(JMM)及volatile关键字 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型( ...
- 深入理解Java内存模型JMM与volatile关键字
深入理解Java内存模型JMM与volatile关键字 多核并发缓存架构 Java内存模型 Java线程内存模型跟CPU缓存模型类似,是基于CPU缓存模型来建立的,Java线程内存模型是标准化的,屏蔽 ...
- Java内存模型之分析volatile
前篇博客[死磕Java并发]—–深入分析volatile的实现原理 中已经阐述了volatile的特性了: volatile可见性:对一个volatile的读,总可以看到对这个变量最终的写: vola ...
- java内存模型-final
与前面介绍的锁和 volatile 相比较,对 final 域的读和写更像是普通的变量访问.对于final 域,编译器和处理器要遵守两个重排序规则: 在构造函数内对一个 final 域的写入,与随后把 ...
- 深入理解java虚拟机(6)---内存模型与线程 & Volatile
其实关于线程的使用,之前已经写过博客讲解过这部分的内容: http://www.cnblogs.com/deman/category/621531.html JVM里面关于多线程的部分,主要是多线程是 ...
- 全面理解Java内存模型(JMM)及volatile关键字
[版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/72772461 出自[zejian ...
- Java并发编程:JMM (Java内存模型) 以及与volatile关键字详解
目录 计算机系统的一致性 Java内存模型 内存模型的3个重要特征 原子性 可见性 有序性 指令重排序 volatile关键字 保证可见性和防止指令重排 不能保证原子性 计算机系统的一致性 在现代计算 ...
- 简要概述java内存模型,以及volatile关键字
如果我们要想深入了解Java并发编程,就要先理解好Java内存模型.Java内存模型定义了多线程之间共享变量的可见性以及如何在需要的时候对共享变量进行同步.原始的Java内存模型效率并不是很理想,因此 ...
随机推荐
- SQL Server 分页SQL
SELECT * FROM(SELECT ROW_NUMBER() OVER(order by Id DESC)AS rownum, (SELECT COUNT(*) FROM Ana_Strateg ...
- linux下共享热点抓包
Linux有一个抓包工具叫tcpdump,这个命令还是挺强大的.简单列举一下它的参数 # tcpdump -h tcpdump version 4.9.2 libpcap version 1.8.1 ...
- GitLab端口冲突 解决办法
访问gitlab,出现:502 GitLab在使用的过程中,会开启80端口,如果80端口被其他的应用程序占用,则GitLab的该项服务不能使用,所以访问GitLab会失败.大多数皆是此问题. ...
- 华硕B360主板装机找不到固态硬盘启动
1.开机点按F2进入BIOS中,在security选项卡中选择secure boot menu,secure boot control按Enter选择Disable,按F10保存: 2.电脑重 ...
- linux 启动tomcat
操作步骤: 第一步:进入tomcat的bin目录 cd /usr/local/tomcat/bin 第二步:使用tomcat关闭命令 ./shutdown.sh 第三步:查看tomcat是否关闭 ps ...
- c3p0的错误mchange.v2.ser.Indirector
mchange-commons-java-0.2.11.jar 没有会报错 (java.lang.NoClassDefFoundError:com.mchange.v2.ser.Indirec ...
- 移动端的文本框获取焦点时导致fixed或absolute定位的按钮被手机键盘顶上去的问题
var win_h = $(window).height();//关键代码 window.addEventListener('resize', function () { if($(window).h ...
- linux下安装压缩解压程序7z命令及7z命令的使用
1.1 在线安装如果你的宿主机Linux可以连接外网,推荐用这种方式,方便简单,执行命令:sudo apt-get install p7zip即可在线安装7z命令. 1.2 安装包安装7z(准确点说是 ...
- Python——变量的作用域
原创声明:本文系博主原创文章,转载及引用请注明出处. 1. 在编程语言中,变量都有一定的作用域,用来限定其生命周期,且不同类型的变量作用域不同. 在Python中解释器引用变量的顺序(优先级)为:当前 ...
- Java io 理解
任何程序都有io部分,io是对程序来说数据流的输入和输出.这里说的流,是指有字节组成的列,不断输入程序,或者从程序中输出,我们形象称为流.Java的io流有两种,一种叫字节流,最原始的:一种叫字符流. ...