在java4和java5中使用volatile关键字

a L*_*ner 6 java

volatile keyword在java4和java5之后使用有什么区别?

与此相关,

非原子变量(long/double)的读/写操作在声明为volatile时是原子的.

这对java4也是如此,或者从java5开始有效吗?

Cra*_*lus 5

是,有一点不同。
Java 4 之前的volatile版本可能会被编译器对之前的任何读取或写入进行重新排序,从而导致微妙的并发错误,例如无法实现锁定double check(对于单例来说这是非常常见的习惯用法)。这个问题在 Java 5.0 中得到了修复,它扩展了不能再针对任何后续读取或写入进行重新排序的
语义,并引入了新的内存模型。volatile您可以阅读此双重检查锁定作为示例参考


a L*_*ner 3

人们在回答我的问题第一部分时提供了很好的观点和参考。

具体到问题的第二部分,我在某个论坛上读到:

声明为 long 的 volatile 是原子的(Java 5 之前也是如此),因为它保证(对于所有 JVM 实现)读取或写入直接到主内存而不是两个 32 位寄存器。

在 Java 5 之前, volatile 应该long 和 double 提供这样的保证。然而,实际情况并非如此,并且实施经常违反这一保证。我记得这个问题似乎在 JDK 1.4 左右得到了解决,但由于他们仍在研究整个内存模型的事情,所以直到 JDK 5 宣布新规则和内存时,他们才真正对此做出任何明确的公告。保证实际上是有意义的。

这是来自Java 语言规范,第二版

17.4 double 和 long 的非原子处理

即使变量的类型是 double 或 long,对 volatile 变量的加载、存储、读取和写入操作也是原子的。