• volatile


    内存屏障

    内存屏障(Memory Barrier)又称内存栅栏,是一个CPU指令,它的作用有两个:

    • 保证特定操作的顺序
    • 保证某些变量的内存可见性(利用该特性实现volatile的内存可见性)

    volatile 变量修饰符

            volatile 关键字是一种类型修饰符,被它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。声明时语法如下:

     int volatile vInt;

    volatile修饰的变量特性

    1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
    2)禁止进行指令重排序

            如何实现可见性,首先被volatile关键字修饰的共享变量在转换成汇编语言时,会加上一个以lock为前缀的指令,当CPU发现这个指令时,立即做两件事:

    1.将当前内核高速缓存行的数据立刻回写到内存;

    2.使在其他内核里缓存了该内存地址的数据无效。

    MESI协议:缓存一致性协议,该协议解决缓存一致性的思路是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,那么他会发出信号通知其他CPU将该变量的缓存行设置为无效状态。当其他CPU使用这个变量时,首先会去嗅探是否有对该变量更改的信号,当发现这个变量的缓存行已经无效时,会从新从内存中读取这个变量。
     

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

    volatile优缺点

     使用volatile的好处:从底层实现原理我们可以发现,volatile是一种非锁机制,这种机制可以避免锁机制引起的线程上下文切换和调度问题。因此,volatile的执行成本比synchronized更低。

      volatile的不足:使用volatile关键字,可以保证可见性,但是却不能保证原子操作


    线程安全获得保证

    工作内存与主内存同步延迟现象导致的可见性问题

    • 可通过synchronized或volatile关键字解决,他们都可以使一个线程修改后的变量立即对其它线程可见

    对于指令重排导致的可见性问题和有序性问题

    • 可以使用volatile关键字解决,因为volatile关键字的另一个作用就是禁止重排序优化

    Volatile关键字常用的场景


    通常volatile关键字被用于以下的几个地方:
    1、中断服务程序中修改的供其它部分程序检测的共享变量。
    2、多任务环境下各个任务的共享标志应该加volatile。
    3、存储器的硬件寄存器需要加volaile说明,因为对它的每次读写都有不同的含义。

  • 相关阅读:
    小程序如何设置用户同意服务协议并上传头像和昵称
    .NET 8 的 green thread 异步模型被搁置了
    react 也就这么回事 02 —— JSX 插值表达式、条件渲染以及列表渲染
    redis
    统计信号处理基础 习题解答6-7
    macos苹果电脑清理软件有哪些?cleanmymac和腾讯柠檬哪个好
    MySQL8 创建函数报错:This function has none of DETERMINISTIC
    Apple developer证书、标识符和描述文件
    像图一样交流:为大语言模型编码图
    “香蕉大王”的转型升级,能否扩大市场份额?
  • 原文地址:https://blog.csdn.net/u013827488/article/details/126085164