java

Volatile

2022-06-27  本文已影响0人  Zeppelin421

volatile 是 Java 中的关键字,是一个变量修饰符,被用来修饰会被不同线程访问和修改的变量

语义

一旦一个共享变量被 volatile 修饰之后,就具备两层语义

作用

实现原理

字节码层面

ACC_VOLATILE

JVM层面(规范)

为了实现 volatile 的内存语义,JMM会限制特定类型的编译器和处理器重排序,JMM会针对编译器制定 volatile 重排序规则表,“NO”表示禁止重排序。


编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。

Hotspot实现

bytecodeinterpreter.cpp0

int field_offset = cache->f2_as_index();
if (cache->is_volatile()) {
    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
        OrderAccess::fence();
    }
}

orderaccess_linux_x86.inline.hpp

inline void OrderAccess::fence() {
   // always use locked addl since mfence is sometimes expensive
#ifdef AMD64
  __asm__ volatile ("lock; addl $0,0(%%rsp)" : : : "cc", "memory");
#else
  __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory");
#endif
  compiler_barrier();
}

如果硬件架构本身已经保证了内存可见性(单核处理器、一致性足够的内存模型),或者硬件架构本身不进行处理器重排序,或者有更强的重排序语义(能够分析多核间的数据依赖),那么volatile就是一个空标记,不会插入相关语义的内存屏障。

查看源代码,可以看到在汇编层面,带有 volatile 修饰的变量前面会有lock add1 $0x0, (%rsp)这么一串指令,由此可见 volatile 是通过LOCK指令前缀来达到内存屏障的作用。

上一篇下一篇

猜你喜欢

热点阅读