int 基本类型的 volatile 声明
volatile declaration on int primitive type
我引用的是关于 Atomic Access
的 Oracle 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
的工作原理。但是提到在第二个语句中为 long
和 double
变量明确声明 volatile
以获得原子访问的要求,是为引用变量和大多数原始变量进行 volatile
声明(除 long 和 double 之外的所有类型)在第一个语句中可选。
但我看到代码在 int
原始类型中使用显式 volatile
声明来实现原子访问;并且不这样做不能保证原子访问。
int variable1; // no atomic access
volatile int variable2; // atomic access
我错过了什么吗?
第一条声明不涉及制作引用变量和原始变量(long
和double
除外)volatile
.
它说 读取 和 写入 所有参考变量和除 long
和 double
之外的所有原语是atomic(默认)。要使 读取 和 写入 long
和 double
atomic,他们需要成为 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
(例如)是 atomic 但你仍然需要 volatile 如果您希望分配对任何 后续 阅读线程可见。
Reading/Writing 到 long/double 变量是一个复合操作并使其成为 volatile 确保它是原子的。
volatile
关键字不仅仅保证原子访问,它还附带 可见性保证。
因为 double
和 long
原语需要 int
(64 位)的 space 的两倍,更新它们的值可以发生在两个 32 位块中。因此,如果没有 volatile,您可以在这两个步骤之间看到 long
或 double
的值。其他原始变量不是这种情况。
但是原子访问与可见性不同。 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 可变变量
我引用的是关于 Atomic Access
的 Oracle 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
的工作原理。但是提到在第二个语句中为 long
和 double
变量明确声明 volatile
以获得原子访问的要求,是为引用变量和大多数原始变量进行 volatile
声明(除 long 和 double 之外的所有类型)在第一个语句中可选。
但我看到代码在 int
原始类型中使用显式 volatile
声明来实现原子访问;并且不这样做不能保证原子访问。
int variable1; // no atomic access
volatile int variable2; // atomic access
我错过了什么吗?
第一条声明不涉及制作引用变量和原始变量(long
和double
除外)volatile
.
它说 读取 和 写入 所有参考变量和除 long
和 double
之外的所有原语是atomic(默认)。要使 读取 和 写入 long
和 double
atomic,他们需要成为 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
(例如)是 atomic 但你仍然需要 volatile 如果您希望分配对任何 后续 阅读线程可见。
Reading/Writing 到 long/double 变量是一个复合操作并使其成为 volatile 确保它是原子的。
volatile
关键字不仅仅保证原子访问,它还附带 可见性保证。
因为 double
和 long
原语需要 int
(64 位)的 space 的两倍,更新它们的值可以发生在两个 32 位块中。因此,如果没有 volatile,您可以在这两个步骤之间看到 long
或 double
的值。其他原始变量不是这种情况。
但是原子访问与可见性不同。 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 可变变量