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内存模型效率并不是很理想,因此 ...
随机推荐
- JVM学习笔记(一):Java虚拟机和虚拟机内存区域
为什么Java程序需要运行在虚拟机上 因为Java在设计之初的跨平台特性,我们知道Java程序是运行在Java虚拟机上的.如果你要问为什么Java程序要运行在虚拟机上,我可以反问你几个问题. 为什么买 ...
- 日常开发用Windows 好还是 Ubuntu好?
最近打算给电脑重新装系统,纠结了很久,不知道应该是换Windows还是Ubuntu,今天通过我自身的体验,来为大家分析一下,日常开发环境到底是用Windows和Ubuntu. [系统介绍] Windo ...
- Odoo的菜单项
用户界面的入口是菜单项,菜单项形成一个层级结构,最顶级项为应用,其下一级为每个应用的主菜单.还可以添加更深的子菜单.可操作菜单与窗口操作关联,它告诉客户端在点击了菜单项后应执行什么操作. 菜单项存储在 ...
- nacos 1.1.x 集群部署笔记
Nacos 是什么? https://nacos.io/zh-cn/docs/what-is-nacos.html 服务(Service)是 Nacos 世界的一等公民.Nacos 支持几乎所有主流类 ...
- java8学习之方法引用详解及默认方法分析
方法引用: 之前花了很多时间对Lambda表达式进行了深入的学习,接下来开启新的主题---方法引用(Method References),其实在之前的学习中已经使用过了,如: 那方法引用跟Lambda ...
- 51Nod 1831 PN表
打出PN表来 发现合数除16,34,289都是赢 质数除2,17都是输 #include<bits/stdc++.h> using namespace std; bool prime(in ...
- 基于Kibana的可视化监控报警插件sentinl入门
sentinl是什么 Kibi/Kibana Alert & Reporting App Watching your data, 24/7/365 sentinl是一个免费的kibana预警与 ...
- 什么是JWT?Token与Session的区别?
什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点 ...
- gtid 1032同步异常处理
gtid 1032同步异常处理 .sql # 在从库中执行 ; ,); ,); ,); ,); ; mysql> select * from fudao_student_lable; +--- ...
- 【agc004d】Teleporter
题目大意 一棵树,改变一些边的父亲,使得深度不超过k. 解题思路 我一开始就想到了贪心,结果莫名其妙的把这种方法给否决了, 然后考虑优化树形dp,然后优化失败⊙﹏⊙ 贪心思路很简单,也很好感受出来,从 ...