多线程--volatile

多线程--volatile

  1. 要想深入了解volatile,首先需要了解缓存一致性协议、指令重排和内存屏障

    1. 缓存一致性协议
      1. 由于CPU运行速度很快,内存运行速度很慢,频繁的读取内存中的数据显然效率不高,所以CPU会通过读取缓存行(一行64个字节,因为CPU寄存器就是64个字节)的方式将内存中可能使用的数据读入CPU内部。但在读取缓存过程中别的进程可能会修改数据,这样就会导致数据不一致的问题,所以需要缓存一致性协议。
      2. 缓存一致性有很多种实现方式,目前windows上最主流的实现方式是MESI
      3. 使用MESI,缓存行就会有4种不同的状态
        1. Modified(M):这行数据有效,数据被修改了,和内存中的数据不一致,数据只存在于本Cache中
        2. Exclusive(E):这行数据有效,数据和内存中的数据一致,数据只存在于本Cache中
        3. Share(S):这行数据有效,数据和内存中的数据一致,数据存在于很多Cache中
        4. Invalid(I):这行数据无效
        5. MESI主要原理就是缓存行在不同的状态间切换,实现缓存一致(比如线程A将数据改了,那么此时A中的缓存行会从S状态变为M状态,线程B中拥有被修改数据的缓存行会变成I状态,当A将数据更新到内存且B重新读取并更新了数据后,A和B状态都会变为S)
    2. 指令重排:由于CPU读取内存效率较低,所以CPU在保证结果不变的情况下有可能会先执行后面的指令。指令重排图示:
      在这里插入图片描述
    3. 内存屏障:主要是为了防止发生指令重排,在JVM层面和CPU层面有不同的实现
      1. JVM层面:顾名思义,将上下两条指令通过一道屏障想隔开,相互间不能打乱顺序执行
        1. LoadLoad屏障:在Load2及后续读取操作要读取的数据被访问前,保证Load2要读取的数据被读取完毕(Load1;LoadLoad;Load2)
        2. StoreStore屏障:在Store2及后续写入操作执行前,保证Store1的写入操作对其他处理器可见(Store1;StoreStore;Store2)
        3. LoadStore屏障:在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕(Load1;LoadStore;Store2)
        4. StoreLoad屏障:在Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见(Store1;StoreLoad;Load2)
      2. CPU层面:CPU层面 上虽然有3条原语支持内存屏障(sfence,ifence,mfence),但是由于并不是所有CPU都支持这3条原语,所以HotSpot虚拟机实现内存屏障的方式为通过lock指令去锁总线,当有CPU在修改数据时禁止其它CPU访问,借此来实现内存屏障
  2. volatile的作用

    1. 线程间相互可见。对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入,小示例
      在这里插入图片描述

    2. 虽然volatile能使线程间可见,但其并不是线程安全的,因为它虽然能将修改后的值很快的写内存中,但是并不能阻止其它线程去取值,比如线程A将0改为了1,其它线程看见了,但是同时拿的1,这样就是线程不安全的了!,案例
      在这里插入图片描述

    3. 防止出现指令重排(比如使用DCL单例的时候,如果不加volatile可能在高并发环境下出现指令重排,返回一个半初始化对象)

  3. volatile实现原理:

    1. 通过插入内存屏障指令禁止编译器和CPU对程序进行重排序
    2. 当对声明了volatile的变量进行写操作时,JVM就会向处理器发送一条Lock前缀的指令,这条Lock前缀指令产生如下两个作用:
      1. Lock前缀指令会引起处理器缓存回写到系统内存,并使用缓存一致性机制来确保回写的原子性
      2. 一个处理器的缓存回写到系统内存会导致其他处理器的缓存无效。处理器使用MESI控制协议去维护内部缓存和其他处理器缓存的一致性。处理器能嗅探其他处理器访问系统内存和它们的内部缓存。处理器使用嗅探技术保证它的内部缓存、系统内存和其他处理器的缓存的数据在总线上保持一致。例如,在Pentium和P6 family处理器中,如果通过嗅探一个处理器来检测其他处理器打算写内存地址,而这个地址当前处于共享状态,那么正在嗅探的处理器将使它的缓存行无效,在下次访问相同内存地址时,强制执行缓存行填充
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值