Volatile如何保证可见性和有序性?

本文详细阐述了Volatile关键字如何通过MESI缓存一致性协议确保线程间的可见性,并介绍了嗅探机制在其中的作用。同时,讲解了Volatile如何通过内存屏障防止指令重排,以保证多线程环境下的有序性。尽管Volatile无法提供原子性,但它在可见性和有序性控制上发挥关键作用。
摘要由CSDN通过智能技术生成

一、Volatile保证可见性

  • Volatile是通过MESI缓存一致性协议来保证可见性
  • 什么是MESI协议?
    • MESI协议其实是一个变量在内存中的不同状态!MESI 是指4中状态的首字
      • M 修改 (Modified) 当一个线程要修改便令
      • E 独享、互斥 (Exclusive) 当一个线程拿到了共享变量,此时为独享状态!
      • S 共享 (Shared) 当多个线程都拿到了共享变量,此时为共享状态!
      • I 无效 (Invalid) 线程丢弃了自己工作内存中的变量,为无效状态!
  • MESI协议如何保证可见性?
    • 首先cpu会根据共享变量是否带有Volatile字段,来决定是否使用MESI协议保证缓存一致性。
    • 如果有Volatile,汇编层面会对变量加上Lock前缀,当一个线程修改变量的值后,会马上经过store、write等原子操作修改主内存的值(如果不加Lock前缀不会马上同步),为什么监听到修改会马上同步呢?就是为了触发cpu的嗅探机制,及时失效其他线程变量副本。
  • cpu总线嗅探机制
    • cpu总线嗅探机制监听到这个变量被修改,就会把其他线程的变量副本由共享S置为无效I,当其他线程在使用变量副本时,发现其已经无效,就回去主内存中拿一个最新的值。
  • 在写入主内存时为什么要加锁?在哪里加锁?
    • 变量被修改后同步到主内存的过程中会在store之前加锁写完后解锁,这个锁只有在修改的时候才会加,锁粒度非常小。
    • 因为在store时可能已经经过了总线,但此时还没有write进主内存,总线却触发了嗅探机制,其他线程的变量已失效,当其他线程去主内存读最新数据时,新数据还未write进来,产生脏数据!
  • Lock前缀的作用
    • 使CPU缓存数据立即写会主内存(Volatile修饰的变量会带lock前缀)
    • 触发总线嗅探机制缓存一致性协议MESI来失效其他线程的变量
      在这里插入图片描述

二、Volatile保证有序性

  • 多线程环境下,有序性问题产生的主要原因就是执行重排优化,而Volatile的另一个作用就是禁止指令重排优化。具体是通过对Volatile修饰的变量增加内存屏障来完成的!

  • 写屏障【给Volatile变量赋值】

    • 写屏障会确保指令重排序时,不会将写屏障之前的代码排在写屏障之后
     public void actor2(I_Result r) {
      num = 2;
      ready = true; //  ready是被volatile修饰的 , 赋值带写屏障
      // 写屏障
     }
    
  • 读屏障【读取Volatile变量的值】

    • 读屏障会确保指令重排序时,不会将读屏障之后的代码排在读屏障之前
     public void actor1(I_Result r) {
      // 读屏障
      //  ready是被volatile修饰的 ,读取值带读屏障
      if(ready) {
         r.r1 = num + num;
      } else {
         r.r1 = 1;
      }
     }
    

    在这里插入图片描述

  • 注意:【因此Volatile无法保证原子性】

    • 写屏障仅仅是保证之后的读能够读到最新的结果,但不能保证其它线程的读跑到它前面去。有序性的保证只是保证了本线程内相关代码不被重排序,无法保证其他线程的读写指令交错,所以Volatile无法保证原子性!!!!!

参考文献:

volatile是怎么保证可见性和有序性的
黑马程序员JUC课程

  • 10
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值