voliate关键字原理

article/2025/9/19 21:56:16

被volatile修饰的变量在编译成字节码文件时会多个lock指令,该指令在执行过程中会生成相应的内存屏障,以此来解决可见性跟重排序的问题。

预备知识
  • 指令重排序
    • 为什么到指令重排序:一般来说,处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行先后顺序同代码中的顺序一致,但是它会保证程序最终执行结果和代码顺序执行的结果是一致的。
    • 指令重排序遵守的准则:编译器和处理器在重排序时,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。
    • 什么办法来禁止指令重排序呢:添加内存屏障
  • 内存屏障
    • 内存屏障分类:内存屏障分为两种:Load Barrier 和 Store Barrier即读屏障和写屏障。
    • 内存屏障作用:
      (1)阻止屏障两侧的指令重排序,即屏障下面的代码不能和屏障上面的代码交换顺序(静止重排序)
      (2)在有内存屏障的地方,线程修改完共享变量以后会马上把该变量从本地内存写回到主内存,并且让其他线程本地内存中该变量副本失效(使用MESI协议)(线程可见性)
      对于Load Barrier来说,在指令前插入Load Barrier,可以让高速缓存中的数据失效,强制从新从主内存加载数据;
      对于Store Barrier来说,在指令后插入Store Barrier,能让写入缓存中的最新数据更新写入主内存,其他线程程可见
voliate关键字作用
  • 静止重排序: voliate修饰的变量,保证变量赋值操作的顺序与程序代码中的执行顺序一致

  • 线程可见性: 当一条线程修改了voliate变量的值,新值对于其他线程来说是可以立即得知的

原理
  • volatile关键字修饰的变量会存在一个“lock:”的前缀,Lock不是一种内存屏障,但是它能完成类似内存屏障的功能。Lock会对CPU总线或高速缓存加锁(一般只是对缓存行枷锁),可以理解为CPU指令级的一种锁。
  • 在具体的执行上,它先对总线或缓存加锁,然后执行后面的指令,在Lock锁住总线的时候,其他CPU的读写请求都会被阻塞,直到锁释放。最后释放锁后会把高速缓存中的脏数据(修改过的数据)全部刷新回主内存,且这个写回内存的操作会使在其他CPU里缓存了该地址的数据无效。
  • 在java内存层面可以理解为:当需要使用(use)这个变量时,必须从主存中read–>load这个变量(即要使用这个变量时,必须从主存中读取这个变量,这就保证了该变量是最新的);当线程工作内存中这个变量被赋值时(assign),那么立刻store–>write这个变量(即当该值计算完成,立刻把这个变量写会主存,并且使得该值在其他内存的工作变量中无效)
java内存屏障

在这里插入图片描述

volatile语义中的内存屏障

volatile的内存屏障策略非常严格保守,非常悲观且毫无安全感的心态:

  • 在每个volatile写操作前插入StoreStore屏障(这个屏障前后的2个Store指令不能交换顺序),在写操作后插入StoreLoad屏障(这个屏障前后的2个Store Load指令不能交换顺序);
  • 在每个volatile读操作前插入LoadLoad屏障(这个屏障前后的2个Load指令不能交换顺序),在读操作后插入LoadStore屏障(这个屏障前后的2个Load Store指令不能交换顺序);

由于内存屏障的作用,避免了volatile变量和其它指令重排序、线程之间实现了通信,使得volatile表现出了锁的特性。
在Java中对于volatile修饰的变量,编译器在生成字节码时,会在指令序列中插入内存屏障禁止处理器重排序。

举例

两条线程Thread-A与Threab-B同时操作主存中的一个volatile变量i时。Thread-A写了变量i,那么:
Thread-A发出LOCK#指令
(1)发出的LOCK#指令锁总线(或锁缓存行)(因为它会锁住总线,导致其他CPU不能访问总线,不能访问总线就意味着不能访问系统内存),然后释放锁,最后刷新回主内(瞬间完成的,写回时候其他缓存行失效),同时让Thread-B高速缓存中的缓存行内容失效。
(2)Thread-A向主存回写最新修改的i
Thread-B读取变量i,那么:
Thread-B发现对应地址的缓存行被锁了,等待锁的释放,缓存一致性协议会保证它读取到最新的值(重新从主存读)
由此可以看出,volatile关键字的读和普通变量的读取相比基本没差别,差别主要还是在变量的写操作上。

举例

在这里插入图片描述

使用场景

满足以下两点,那么volatile修饰的共享变量,不用加锁也能保证线程安全:

  • 运算结果不依赖变量的当前值(即变量计算的结果和当前的值没有关系,比如一个boolean变量的改变,但是i++这种运算就存在依赖关系,以为新值是在旧值的基础上加1),或者能够确保只有单一的线程修改变量的值
  • 变量不需要与其他的状态变量共同参与不变性约束(即该变量不和其他变量关联)

http://chatgpt.dhexx.cn/article/TxHIFps1.shtml

相关文章

voliate关键字

voliate关键字详解: 1.内存模型相关概念 物理计算机内存访问图: 任何计算都是在CPU内处理的,那么也就必须涉及到数据读写,但是CPU每次都要和主内存交互读写数据效率太低了,于是有了高速缓存。在程序运行时&#xff…

java面试题:voliate底层原理——详解

1. voliate底层原理 1.1 voliate变量的特点 可见性: 当一个线程修改了声明为volatile变量的值,新值对于其他要读该变量的线程来说是立即可见的。有序性: volatile变量的所谓有序性也就是被声明为volatile的变量的临界区代码的执行是有顺序的…

FSM有限状态机(三段式)-Verilog实现

一. 状态机理论基础 状态机基本概念: 状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定操作的控制中心。 以上是标准解释,其实状态机就是为了解决比如IIC协…

Verilog描述有限状态机(一段式、二段式、三段式)

有限状态机(FSM)的输出取决于过去状态以及当前输入,是时序逻辑电路。适合描述那些发生有先后顺序或者有逻辑规律的事情,状态机的本质就是对具有逻辑顺序或时序规律的事件进行描述的一种方法,广泛用于多种场合。 因此&…

以爱情规律为例,浅谈三段式描述状态机

目录 基础概念介绍 状态机的要素 FSM的分类 Verilog描述状态机的方法 一段式描述 两段式描述 三段式描述 结语 基础概念介绍 今夜闲来无事,忽然想到最近准备复习一下Verilog语法,所以就侃一侃状态机吧! 状态机根据状态的数量可以分为两…

三段式状态机-FSM

三段式代码多,但是有时钟同步,延时少,组合逻辑跟时序逻辑分开并行出错少。 (1)同步状态转移 (2)当前状态判断接下来的状态 (3)动作输出 如果程序复杂可以不止三个always 。always 后常接cas…

一段式、两段式和三段式状态机

这里写自定义目录标题 一段式两段式三段式 这张图片是mealy型状态机的结构,Moore型类似,输出与输入无关。 一段式 module moduleName (input clk,input rst_n,input in,output reg [3:0] out );localparam s14d0, s24d1, s34d2, s44d3, s54d4; reg [3:…

FPGA开发基础之三段式状态机

状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,程序的运行其本质也是状态机,根据输入完成输出,得到新的状态。 在平时硬件电路的设计中经常需要用到状态机,例如CPU的取指、译…

关于三段式状态机第三段是组合逻辑还是时序逻辑的问题?

由于本人一直以来,用的三段式状态机,第三段写法都是组合逻辑写法,但是近期有小伙伴面试小公司,写到状态机的第三段时候,按照我一直用到的组合逻辑来写第三段,提供输出,被提出了质疑,…

【状态机设计】Moore、Mealy状态机、三段式、二段式、一段式状态机书写规范

目录 状态机介绍 状态机类型 Moore 型状态机 Mealy 型状态机 状态机设计流程 自动售卖机 状态机设计:3 段式(推荐) 实例 实例 状态机修改:2 段式 实例 状态机修改:1 段式(慎用) 实…

状态机的描述方法案例分析(一段式、二段式、三段式)

上篇博文讲了:FPGA中有限状态机的状态编码采用格雷码还是独热码? 那篇博文讲了状态机的状态编码是用格雷码还是独热码的问题,以及两者之间的优劣。状态机的描述方式采用的是一段式描述方式,也就是将整个状态机全部写到一个always…

FPGA状态机(一段式、二段式、三段式)、摩尔型(Moore)和米勒型(Mealy)

1、状态机 1.1、理论 FPGA不同于CPU的一点特点就是CPU是顺序执行的,而FPGA是同步执行(并行)的。那么FPGA如何处理明显具有时间上先后顺序的事件呢?这个时候我们就需要使用到状态机了。 状态机简写为 FSM(Finite Sta…

三段式状态机_verilog

这是一篇转载的文章,但是个人理解笔者将前两个always块结构搞错了,自行纠正了一下。 原文链接 https://www.jianshu.com/p/5eee434ab24d 1. 三段式要求 有限状态机采用三段式风格,即三个always块描述状态机. 第一个时序逻辑always块用来描…

2021-08-21Verilog三段式状态机的写法,标准示例和仿真。

Verilog三段式状态机的写法,标准示例和仿真。 第一段:同步状态转移。第一个always块格式化描述次态寄存器迁移到现态寄存器。 第二段:当前状态判断接下来的状态。组合逻辑always模块,描述状态转移条件判断用current_state 第三段&…

verilog 3段式状态机

3段式状态机: 3段式状态机写法,写出下图状态转换图。 1 确定输入输出信号,及其类型(是wire还是reg); 2 声明内部信号,一般需要定义current_state和next_state; 3 用3个always语句描…

三段式状态机设计

状态机设计需满足的几个要求: 1. 三段式要求 有限状态机采用三段式风格,即三个always块描述状态机. 第一个组合逻辑always块用来描述下一状态的转移(next state logic) 第二个时序逻辑always块用来描述当前状态.(cur…

三段式状态机浅析

三段式状态机 文章目录 三段式状态机三段式状态机优点书写格式formater整形器状态机书写举例 关注作者 三段式状态机优点 将组合逻辑与时序逻辑分开,所写代码层次清晰,方便理解和后续的维护相较两段式状态机,解决了输出毛刺的影响。 书写格…

(三段式)有限状态机【原理+实例】

状态机的基本要素:输入、输出、状态。 状态机根据状态变化是否与输入条件有关分为两类:即Moore型状态机和Mealy型状态机。 Moore型状态机的状态变化仅和当前状态有关,而与输入条件无关; Mealy型状态机的状态变化不仅和当前状态…

状态机设计(一段式、两段式和三段式)

三段式状态机 第一段,时序always块,状态跳转 第二段,组合always块,状态更新 第三段,时序always块,输出控制 两段式状态机 两段式状态机是把三段式状态机的第二段和第三段合为一段,那么两段式…

FPGA——三段式状态机(1)

状态机全称是有限状态机(Finite State Machine、FSM),是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。状态机可根据控制信号完成预定的状态转换,由组合逻辑电路和寄存器组成,可由状态转换表或状态转…