int原语类型的volatile声明

时间:2018-05-16 15:10:24

标签: java concurrency atomic volatile

我引用了Atomic Access

上的Oracle Java文档
  
      
  • 读取和写入对于引用变量和大多数原始变量(除long和double之外的所有类型)都是原子的。
  •   
  • 对于声明为volatile的所有变量(包括长变量和双变量),读取和写入都是原子的。
  •   

我理解volatile的工作原理。但是提到明确声明volatile longdouble变量以在第二个语句中获得原子访问的要求,是对参考变量和大多数原始变量进行volatile声明(在long和double之外的所有类型)第一个语句中可选。

但我看到代码在volatile基元类型中使用显式int声明来实现原子访问;并且不这样做不保证原子访问。

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

我错过了什么吗?

2 个答案:

答案 0 :(得分:7)

第一个语句不是指引用变量和原始变量(longdouble除外) volatile

它说读取所有引用变量的,除longdouble之外的所有原语都是原子 (默认情况下)。要使读取 longdouble 原子,他们需要volatile。< / p>

原子性与可见性没有任何关系。

关于同一文档的以下段落

  

原子操作不能交错,因此可以使用它们而不用担心线程干扰。但是,这并不能消除所有同步原子操作的需要,因为仍然可能存在内存一致性错误。使用volatile变量可以降低内存一致性错误的风险,因为对volatile变量的任何写入都会建立与之后读取同一变量的先发生关系。

因此,像a = 1这样的语句aint(例如) atomic ,但你仍然需要 volatile 如果您希望任何后续读取线程可以看到该分配。

读取/写入long / double变量是一个复合动作,并使其 volatile 确保它是原子的。

答案 1 :(得分:5)

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

doublelong原语占用int(64位)空间的两倍时,它们的值可以在两个32位块中发生。因此,如果没有易失性,您可以在这两个步骤之间看到longdouble的值。其他原始变量不是这种情况。

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

  

当一个字段声明为volatile时,编译器和运行时   我们注意到这个变量是共享的,对它的操作不应该   与其他内存操作重新排序。挥发性变量未缓存   注册或隐藏在其他处理器中的高速缓存中,所以读取一个   volatile变量总是返回任何线程的最近写入。

实践中的Java并发:3.1.4易失性变量