volatile keyword
java4和java5以后使用有什么区别?
并与此相关,
非原子变量(long/double)的读/写操作在声明为 volatile 时是原子的。
这对 java4 也是如此还是从 java5 开始有效???
volatile keyword
java4和java5以后使用有什么区别?
并与此相关,
非原子变量(long/double)的读/写操作在声明为 volatile 时是原子的。
这对 java4 也是如此还是从 java5 开始有效???
是,有一点不同。
编译器可以根据之前的任何读取或写入对 Java 4volatile
进行重新排序,从而导致微妙的并发错误,例如无法实现double check
锁定(单例非常常见的习语)。
这在 Java 5.0 中得到了修复,它扩展了volatile
无法针对任何后续读取或写入重新排序的语义,并引入了新的内存模型。您可以阅读此Double Checked Locking例如参考
该站点很好地解释了这些差异:http ://www.javamex.com/tutorials/synchronization_volatile.shtml
他们还在一个单独的页面上解释了 Java 5 中 volatile 的行为:http ://www.javamex.com/tutorials/synchronization_volatile_java_5.shtml
人们在回答我的问题回答第一部分时提供了很好的观点和参考。
具体到问题的第二部分,这是我在某个论坛上读到的:
声明为 long 的 volatile 是原子的(也是 Java 5 之前的版本),因为它保证(对于所有 JVM 实现)直接读取或写入主内存而不是两个 32 位寄存器。
和
在 Java 5 之前,volatile应该为 long 和 double 提供这样的保证。然而在实践中事情并没有这样发展,并且实现经常违反这个保证。我记得这个问题似乎在 JDK 1.4 附近得到了解决,但是由于他们仍在研究整个内存模型,所以直到 JDK 5 宣布了新规则和内存时,他们才真正做出任何明确的声明。保证实际上意味着什么。
这是来自Java语言规范,第二版:
17.4 double 和 long 的非原子处理
对 volatile 变量的加载、存储、读取和写入操作是原子的,即使变量的类型是 double 或 long。
在 java4 和 java5 以后使用 volatile 关键字有什么区别?
JDK5 之前的 JMM 被破坏并且对 JDK4 使用 volatile 可能无法提供预期的结果。有关更多信息,请查看: http ://www.ibm.com/developerworks/library/j-jtp02244/
非原子变量(long/double)的读/写操作在声明为 volatile 时是原子的。
long/double 的读/写作为两个单独的 32 位操作发生。对于两个线程,一个线程可能读取了高 32 位,而另一个线程读取了 long/double 变量的低 32 位。简而言之,长读/写不像其他原语那样是原子操作。对 long/double 使用 volatile 应该提供这样的保证,因为 volatile 的指令不会被编译器重新排序以进行 volatile 读/写,并且 volatile 还提供可见性保证。但同样,它可能不适用于 JDK 4 或更早版本。