volatile如何实现有序性

之前在java内存模型中提到过volatile,这次更深入一些探究一些volatile到底是怎么实现有序性.

我们分成五个部分来看

  • java源码
  • ByteCode字节码
  • JVM虚拟机规范
  • JVM虚拟机实现
  • CPU级别

volatile五个部分

字节码

源码中使用的volatile关键字在字节码中会被添加一个ACC_VOLATILE的前缀标识

public class VolatileT {
    volatile int i;
}

使用 javap -verbose VolatileT.class 指令进行反编译

  volatile int i;
    descriptor: I
    flags: ACC_VOLATILE

看到,在i的flags中添加了ACC_VOLATILE这个标签,并没有多余的操作

JVM

JVM虚拟机规范规定了四种内存屏障

  • LoadLoad屏障: 在后续load前,保证之前load要读取的数据读取完毕
  • StroeStroe屏障: 在后续store前, 保证之前要store的数据存储完毕
  • LoadStore屏障: 在后续stroe钱,保证之前load要读取的数据读取完毕
  • StroeLoad屏障: 在后续load钱, 保证之前要stroe存储完毕


如果两条指令想要操作同一块内存的话,加一层屏障,不允许这两条指令之间进行重排.

volatile在JVM层面的实现
volatile在写操作的时候,要求前面指令的写完之后再写,后面的指令等待写完之后再读.
volatile在读操作的时候,要求前面的指令读完之后再读,后面的指令等待读完之后再写.

这是JVM规范,具体要看不同虚拟机的实现.

HotSpot实现内存屏障实际使用汇编语言的Lock指令实现的.

CPU

要想实现在一个CPU中修改完,另一个CPU立刻可以感知到,这需要使用缓存一致性协议.

X86CPU内存屏障

  • sfence: 在sfence指令前的写操作必须在sfence指令后的写操作前完成
  • lfence: 在lfence指令前的读操作必须在lfence指令后的读操作前完成
  • mfence: 在mfence指令前的读写操作必须在mfence指令后的读写操作前完成

fence: 栅栏
s: save
l: load
m: memory


   转载规则


《volatile如何实现有序性》 echi1995 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
springIOC springIOC
以前学习spring的时候总是说spring的特点是IOC和AOP,那具体是什么呢?要是让我回答,我可能只知道IOC是一个管理bean的容器,需要使用bean的时候可以由IOC容器自动注入.现在想想,通俗一点说: 我想要吃一些水果,因此有了
下一篇 
redis核心数据结构 redis核心数据结构
之前项目中使用redis就是很简单的将值以键值对的形式放进去,顶多设个过期时间.现在去看了一下redis实际上也提供了很多有用的功能,学习一下以备以后用得上. redis数据结构stringstring就是平常用的键值对,没有太多好说的,很
  目录