JMM同步规范和Volatile重点概要
背景
JMM称为java内存模型,用于规范线程之间的数据共享问题,出现此模型的原因和硬件的发展有关。
早期的单核cpu下不会存在该问题,后来多核cpu和cpu多重缓存机制加快了数据的读写,但是也产生了不同步问题。
JMM之后通过cpu的总线机制优化了这个情况,该总线是主内存和CPU缓存之间的一个过渡区,可以通知各个线程变量变化。加了Volatile的变量可以被总线监视。
过程
如图A所示:
假如某个CPU有两个核心,每个核心执行一个线程,硬件角度上他们两个是不同的寄存器,但是却共享主内存的同一个变量。
刚开始两者都读取同一个变量到自己的线程内(自己的寄存器内),产生各自的一个副本变量,之后线程B修改false变量,此时若变量为一般变量,则不会触发cpu总线机制。
若此时一个Volatile变量发生了变化,总线机制会通过MIES修改变量的信息。
MEIS是缓存一致性,是CPU用来通知线程缓存变化的一种手段,四个字母表示四种状态,从字节级别进行标识变量。
M(Modified):数据被修改了,属于有效状态,但是数据只处于本Cache,和内存不一致。E(Exclusive):数据独占,属于有效状态,数据仅在本Cache,和内存一致。S(Shared):数据非独占,属于有效状态,数据存于多个Cache,和内存一致。I(Invalid):数据无效。
简单来说 ,当关键变量只被一个线程读取时,他的状态是E独享,此时根本不会出现缓存不一致现象,但如果此时又被另外一个线程读取了,总线会通知拥有此线程将此变量的头信息进行修改,标识变成了S,此时如果线程再修改自己寄存器内的变量,由于此时标识是S,则会通知总线,总线再通知将所有拥有此变量的头信息标识改为M,此时其他线程就得知这个变量被修改了,就从主内存中重新刷新数据到自己的线程里,此时标识又会从M改为S。
至于Volatile,打断点可以得知此处是通过C++的Lock机制通知系统底层提示总线进行操作。
图A
Volatile不能保证原子性
传统情况下,一个线程写,多个线程读,写线程的操作会通过MEIS协议告知其他线程刷新值,所以不会出现问题。
但是如果是多线程下,线程A操作完数据并将值刷新到主内存,此时线程B恰好也完成操作,此时却被总线通知要重新读取,结果就会抛弃之前的计算结果,重新读取旧值,又由于缺少CAS的重试,导致之前的操作没有重新再执行,所以1000次累加计算中,总会有几次操作被撤销导致数据丢失。
Volatile的重排序和内存屏障
在多线程环境下,如果一个变量要被多个线程共享,进行写操作时,可能会发生A线程先处理完,之后B再处理,但是A还没有刷新到主内存中,B读取脏数据,成了这样是不符合预期情况的,称为重排序问题。
简单来说就是多个线程将预期的顺序打乱了,会出现预料之外的结果。
加了Volatile的关键字会让CPU把数据及时刷新到主内存中,防止B读取数据时是脏数据,称为内存屏障,这点和事务的脏读有点像。
Volatile导致的重排序和和双层检验锁
new 一个对象的操作实际上是三步:
1.分配对象的内存空间
2.调用构造函数初始化
3.将对象赋值给变量
在多线程环境下,重排序可能会产生对象多次初始化操作。
如:单例双层检验锁中的成员变量若没有Volatile,多线程环境下可能会发生重排序问题导致线程A还没有执行第三步,线程B却又进入到锁中并通过了if又准备执行一遍初始化。
Volatile导致效率变低的原因和伪共享问题
首先确定一个空的java对象在64位环境下占据6个字节,头结点8个字节,,AbstractPaddingObject自动填充字节为8的倍数,可以提高一些性能。
多线程下,一个写线程,多个读线程,因为读线程每次都要从主内存刷新,所以效率降低了一部分。
伪共享问题一般只有在主内存变量加上了Volatile关键字,对另外的线程及时可见,另外线程读取时会以64字节缓存行读取,若没有Volatile则不会出现以64字节行读取主内存。
参考:蚂蚁课堂
JMM同步规范和Volatile重点概要相关推荐
- 并发编程之深入理解JMM并发三大特性volatile
并发编程之深入理解JMM&并发三大特性&volatile 并发和并行 并发三大特性 可见性 有序性 原子性 Java内存模型(JMM) JMM定义 JMM与硬件内存架构的关系 内存交互 ...
- 【并发】2、JMM三大特性与Volatile
JMM三大特性与Volatile 什么是JMM模型 线程,工作内存,主内存工作交互图(基于JMM规范) JVM虚拟机 Java内存模型与硬件内存架构的关系 JMM存在的必要性 数据同步八大原子操作 j ...
- JUC多线程:JMM内存模型与volatile内存语义
一.JMM 内存模型: 1.什么是 JMM 内存模型: Java 内存模型是 Java 虚拟机定义的一种多线程访问 Java 内存各个变量的访问规范,主要围绕如何解决并发过程中的原子性.可见性.有序性 ...
- java基础提升篇:synchronized同步块和volatile同步变量
初遇 Java语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量.这两种机制的提出都是为了实现代码线程的安全性.其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低 ...
- Java线程(二):线程同步synchronized和volatile
上篇通 过一个简单的例子说明了线程安全与不安全,在例子中不安全的情况下输出的结果恰好是逐个递增的(其实是巧合,多运行几次,会产生不同的输出结果),为什么 会产生这样的结果呢,因为建立的Count对象是 ...
- synchronized同步块和volatile同步变量
Java语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量.这两种机制的提出都是为了实现代码线程的安全性.其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低),而 ...
- gb50243-2016通风与空调工程施工质量验收规范_《通风与空调工程施工质量验收规范》GB50243-2016 重点解读...
本文来源 百度文库 筑龙暖通 整理 01 修订简介 修编依据 根据住房和城乡建设部<关于印发(2012 年工程建设标准规范制定修订计划)的通知> (建标{2012}5 号)文的要求,规范编 ...
- MySQL数据库重点概要总结
目录 前言: 1.结构化查询语言(Structured Query Language)简称SQL. 2.基本SELECT语句语法 3.多表链接 4.笛卡尔积 5.ANSI SQL ANSI SQL:1 ...
- 比特未来:《2019上海区块链技能与运用白皮书》要重点概要
9月6日,区块链技能立异峰会在上海杨浦区举办,大会发布了<2019上海区块链技能与运用白皮书>,这份白皮书对我国政府层对区块链的方针扶持.监管,我国区块链职业展开现状以及上海区块链展开状况 ...
- 同步手绘板——重点难点及实现想法
同步手绘板的作用是在没有手绘板的时候可以提供一个与之类似的功能,也更加的方便快捷,但一个软件想要完全代替专业硬件的功能不太现实,只能尽可能的去实现数位板的功能,以达到理想的状态. 1.作为一个绘图软件 ...
最新文章
- MySQL5.5复制新特性
- 不要担心,我可以一个人走
- SQL注入测试平台 SQLol -6.CHALLENGES挑战
- 华为p40鸿蒙系统价格有好高,鸿蒙系统版本华为P50新机的曝光,华为P40处境悲惨价格骤降...
- +new Date()的用法
- 访问CrmService遇到HTTP status 401 Unauthorized的问题
- Visual Studio下的PHP开发工具VS.PHP初探
- SQL PASS北京用户群成功举办第一次线下活动,性能调优PPT分享
- redis运行redis-server.exe错误
- iOS开发日记9-终端命令
- 用最简单的道理说服别人,提升自己
- php . 和..,?php?和??
- c++万能头文件包含的头文件
- python中dot函数总结
- Unity 2D骨骼动画2:创建真实动画
- Suse linux 命令行
- 大小限制_微信突破九张照片,视频大小限制
- python中噪音是什么意思_Perlin噪声和Python的ctypes
- 一位自由职业者的日常
- 为什么要使用回调函数?(这个回答太精彩了)
热门文章
- 自动驾驶 10-1: 3D 几何和参考系3D Geometry and Reference Frames
- 极客大学产品经理训练营:需求评审 第13课总结
- 极客大学产品经理训练营 产品思维和产品意识(上) 第3课总结
- atoi()函数和stoi()函数
- rmi 反序列化漏洞_Java反序列化漏洞自动挖掘方法
- oracle 九阴真精,《九阴真经》真的很强吗?其实它杂而不精,顶级高手都不愿意用...
- matlab聚类分析_数据挖掘——聚类分析
- matplot画图控制marker点的个数_专刊主编述评 中药质量标志物(Qmarker):提高中药质量标准及质量控制理论和促进中药产业科学发展...
- OMP与MP算法流程与代码
- JVM-深入虚拟机字节码执行引擎