关于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
的工作原理。但是在第二条语句中提到为long
和double
变量显式声明volatile
以获得原子访问的要求,使得第一条语句中的引用变量和大多数基本变量(除long和double之外的所有类型)的volatile
声明成为可选的
但是我看到一些代码在int
原语类型中使用显式volatile
声明来实现原子访问;不这样做也不能保证原子访问
int variable1; // no atomic access
volatile int variable2; // atomic access
我错过什么了吗
# 1 楼答案
第一条语句没有提到生成引用变量和基本变量(除了
long
和double
)volatile
它说,读取所有参考变量的和写入,并且除了
long
和double
之外的所有原语都是原子的(默认情况下)。要使long
和double
原子的读取和写入,它们需要是volatile
原子性与可见性无关
同一份文件的以下段落
因此,像
a = 1
,其中a
是一个int
(例如)的语句是原子的,但是如果希望任何后续读取线程都能看到赋值,那么仍然需要volatile读取/写入长/双变量是一个复合动作,使其不稳定可确保其原子性
# 2 楼答案
volatile
关键字不仅保证了原子访问,还提供了可见性保证因为
double
和long
原语占用的空间是int
(64位)的两倍,更新它们的值可以在两个32位的块中发生。因此,如果没有volatile,您可以在这两个步骤之间看到long
或double
的值。其他基本变量的情况并非如此但原子访问与可见性不同。
volatile
关键字还保证在写入变量后,在其他线程上对该变量进行的所有读取都将看到新值。这就是为什么在其他原语类型上仍然需要使用volatile
实践中的Java并发:3.1.4可变变量