Java-并发篇-01-Volatile

1. 概述

volatile是Java虚拟机提供的轻量级的同步机制。

  • 保证可见性(JMM的可见性)
    指的是当主内存区域中的值被某个线程更改后,其他线程会马上知晓更改后的值,并重新获得更改后的值。

  • 不保证原子性
    何为原子性? 即不可分割,完整性,即某个线程正在做某个具体业务时,中间不可被加塞或者被分割,需要整体完整

  • 禁止指令重排
    计算机在执行过程中,为了提高性能,编译器和处理器常常会做指令重排,一般分为以下三种

    • 源代码–>编译器优化的重排–>指令并行的重排–>内存系统的重排–>最终执行的指令
    • 单线程不受影响
    • 处理器在进行指令重排时必须考虑指令之间的数据依赖性

多线程环境中线程交替进行,由于编译器优化重排的存在,两个线程中使用的变量能否保持一致性是无法确定的

2. 可见性

在这里插入图片描述
cpu和主内存是两个独立得硬件,不能直接交互数据,是通过总线来交互数据得。
主内存与cpu之间进行数据交互都会经过总线。

volatile关键字会开启总线得mesi缓存一致性协议

mesi缓存一致性协议:多个CPU从主内存读取同一个数据到各自得高速缓存,当其中某个cpu修改了缓存里得数据,该数据会马上同步回主内存,其他cpu通过总线嗅探机制可以感知到数据得变化从而将自己缓存里得数据失效

在这里插入图片描述

  • 线程2修改值,以后会经过总线,然后写回主内存。
  • volatile开启总线mesi缓存一致性协议,每个cpu 都会监听总线
  • 当知道其他cpu修改了变量值,立刻会失效自己工作内存中得值。
  • 重新去主内存取值。

线程2修改值了以后,会在store之前加锁,锁住主内存得值,这期间其他线程的等锁释放后才能访问,主内存得值修改后会释放锁,这样保障了其他线程读取到得是最新得值。这里锁得颗粒度很小,所以影响忽略不计。这就是Volatile保障可见性得基本原理。

怎么保障读取是最新得值呢?

  • volatile缓存可见性实现原理底层实现主要是通过汇编LOCK前缀指令,它会锁定这块内存区域得缓存(缓存行锁定)并回写到主内存。

3 有序性(禁止指令重排)

因为内存屏障(memory barrier),他是一个CPU指令作用两个:

  • 一是保证特定操作的执行顺序 ,
  • 二是保证某些变量的内存可见性

由于编译器和处理器都能执行指令重排优化,如果在指令之间插入一条Memory barrier则会告诉编译器和CPU,不管什么指令都不能和这条Memory barrier指令重排序,也就说 通过插入内存屏障禁止在内存屏障前后的指令执行重排优化,内存屏障另外一个作用是强制刷出各种CPU的缓存数据,因此任何CPU上的线程都可以读取到这些数据的最新版

对Volatile变量进行写操作时,会在写操作后加入一条Store屏障指令,将工作内存中的共享变量刷新回主内存;
对Volatile变量进行读操作时,会在读操作前加入一条load屏障指令,从主内存中读取共享变量
;


JMM(java memory model): 1.可见性 2.原子性 3.有序性

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alan0517

感谢您的鼓励与支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值