volatile深入

2 篇文章 0 订阅

1.在多个个线程工作内存看起来互无关联的情况下是怎么做到保证变量的可见性的?
最初通过总线,总线就是一条共享的通信链路,它用一套线路来连接多个子系统。最初实现就是通过总线加锁的方式也就是上面的lock与unlock操作,但是这种方式存在很大的弊端。会将我们的并行转换为串行,从而失去了多线程的意义。

因为内存和CPU的速度差太多,为了解决数据不一致问题,在CPU内部设置了少量的高速缓存,目前流行的3级缓存,那么如何在多核情况下又有多个L1级缓存,来保证数据一致性,这时候推出了MESI缓存一致性协议。然后CPU的总线也会开启嗅探机制,这时候一个线程如果将修改之后变量的值传输到总线,会触发总线的嗅探机制,然后会告诉正在使用当前变量的其他线程他们的工作空间的值失效。需要重新去获取这个变量。

底层通过汇编lock前缀指令,它会锁定这块内存区域的缓存(缓存行锁定)并写回到主内存。总的来说就是Lock指令会将当前处理器缓存行数据立即写回到系统内存从而保证多线程数据缓存的时效性。这个写回内存的操作同时会引起在其它CPU里缓存了该内存地址的数据失效(MESI协议)。为了保证在从工作内存刷新回主内存这个阶段主内存数据的安全性,在store前会使用内存模型当中的lock操作来锁定当前主内存中的共享变量。当主内存变量在write操作后才会将当前lock释放掉,别的线程才能继续进来获取新的值。

加了volatile就直接加lock指令
M表示修改,E表示独享,S表示共享,I表示无效
2.为什么volatile不能保证原子性?
假设有两个线程对共享变量进行操作,thread1比thread2先拿到锁,这时候嗅探机制会告诉thread2这个值已经被修改过 了,这时候导致thread2工作空间的值失效,只能再去获取这个值,所以就浪费了一个次机会。从而导致最终的结果小于预期值。
3.volatile禁止指令重排
遵循happens-before原则

程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作。
监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。
volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读。
传递性规则:如果A happens-before B,且B happens-before C,那么A happens-before C。
start()规则:如果线程A执行操作ThreadB.start()(启动线程B),那么A线程的ThreadB.start()操作happens-before于线程B中的任意操作。
join()规则:如果线程A执行操作ThreadB.join()并成功返回,那么线程B中的任意操作happens-before于线程A从ThreadB.join()操作成功返回。
程序中断规则:对线程interrupted()方法的调用先行于被中断线程的代码检测到中断时间的发生。
对象finalize规则:一个对象的初始化完成(构造函数执行结束)先行于发生它的finalize()方法的开始。

volatile通过内存屏障实现了防止指令重排的目的。同时lock前缀指令相当于一个内存屏障,它会告诉CPU和编译器先于这个命令的必须先执行,后于这个命令的必须后执行。内存屏障另一个作用是强制更新一次不同CPU的缓存
例如,一个写屏障会把这个屏障前写入的数据刷新到缓存,这样任何试图读取该数据的线程将得到最新值,而不用考虑到底是被哪个cpu核心或者哪颗CPU执行的。
不同硬件实现内存屏障的方式不同,Java内存模型屏蔽了这种底层硬件平台的差异,由JVM来为不同的平台生成相应的机器码。Java内存屏障主要有Load和Store两类:

对Load Barrier来说,在读指令前插入读屏障,可以让高速缓存中的数据失效,重新从主内存加载数据
对Store Barrier来说,在写指令之后插入写屏障,能让写入缓存的最新数据写回到主内存
为了实现volatile的内存语义,编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。然而,对于编译器来说,发现一个最优布置来最小化插入屏障的总数几乎不可能,为此,Java内存模型采取保守策略:
在每个volatile写操作的前面插入一个StoreStore屏障。
在每个volatile写操作的后面插入一个StoreLoad屏障。
在每个volatile读操作的后面插入一个LoadLoad屏障。
在每个volatile读操作的后面插入一个LoadStore屏障。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值