有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

关于int基元类型的java volatile声明

我引用了Oracle关于Atomic Access的Java文档

  • Reads and writes are atomic for reference variables and for most primitive variables (all types except long and double).
  • Reads and writes are atomic for all variables declared volatile (including long and double variables).

我了解volatile的工作原理。但是在第二条语句中提到为longdouble变量显式声明volatile以获得原子访问的要求,使得第一条语句中的引用变量和大多数基本变量(除long和double之外的所有类型)的volatile声明成为可选的

但是我看到一些代码在int原语类型中使用显式volatile声明来实现原子访问;不这样做也不能保证原子访问

int variable1;          // no atomic access
volatile int variable2; // atomic access

我错过什么了吗


共 (2) 个答案

  1. # 1 楼答案

    第一条语句没有提到生成引用变量和基本变量(除了longdoublevolatile

    它说,读取所有参考变量的写入,并且除了longdouble之外的所有原语都是原子的(默认情况下)。要使longdouble原子的读取写入,它们需要是volatile

    原子性与可见性无关

    同一份文件的以下段落

    Atomic actions cannot be interleaved, so they can be used without fear of thread interference. However, this does not eliminate all need to synchronize atomic actions, because memory consistency errors are still possible. Using volatile variables reduces the risk of memory consistency errors, because any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable.

    因此,像a = 1,其中a是一个int(例如)的语句是原子的,但是如果希望任何后续读取线程都能看到赋值,那么仍然需要volatile

    读取/写入长/双变量是一个复合动作,使其不稳定可确保其原子性

  2. # 2 楼答案

    volatile关键字不仅保证了原子访问,还提供了可见性保证

    因为doublelong原语占用的空间是int(64位)的两倍,更新它们的值可以在两个32位的块中发生。因此,如果没有volatile,您可以在这两个步骤之间看到longdouble的值。其他基本变量的情况并非如此

    但原子访问与可见性不同。volatile关键字还保证在写入变量后,在其他线程上对该变量进行的所有读取都将看到新值。这就是为什么在其他原语类型上仍然需要使用volatile

    When a field is declared volatile, the compiler and runtime are put on notice that this variable is shared and that operations on it should not be reordered with other memory operations. Volatile variables are not cached in registers or in caches where they are hidden from other processors, so a read of a volatile variable always returns the most recent write by any thread.

    实践中的Java并发:3.1.4可变变量