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字节行读取主内存。

 

 

参考:蚂蚁课堂 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值