java - 定义 long 或 double 变量时 volatile 关键字如何影响原子性

标签 java multithreading

我最近正在阅读java中的思维,并对以下内容感到困惑:

However, you do get atomicity (for simple assignments and returns) if you use the volatile keyword when defining a long or double variable (note that volatile was not working properly before Java SE5).

为什么在定义 long 或 double 变量时使用 volatile 关键字可以获得原子性? JVM 允许将 64 位数量(long 和 double 变量)的读写作为两个单独的 32 位操作执行,并且如果我将 long 或 double 变量定义为 volatile,两个独立的 32 位操作将不会被线程机制中断?

全段内容:

Atomicity applies to "simple operations" on primitive types except for longs and doubles. Reading and writing primitive variables other than long and double is guaranteed to go to and from memory as indivisible (atomic) operations. However, the JVM is allowed to perform reads and writes of 64-bit quantities (long and double variables) as two separate 32-bit operations,raising the possibility that a context switch could happen in the middle of a read or write, and then different tasks could see incorrect results (this is sometimes called word tearing, because you might see the value after only part of it has been changed). However, you do get atomicity (for simple assignments and returns) if you use the volatile keyword when defining a long or double variable (note that volatile was not working properly before Java SE5). Different JVMs are free to provide stronger guarantees, but you should not rely on platform-specific features.

volatile 字段会立即写入主内存,并从主内存中进行读取。因此,即使我将 long 或 double 变量定义为 volatile ,32 位操作也可能发生并更改主内存中的 long 或 double 值,此时写入long或double值包含两个32位操作,并且前32位操作可以发生在改变主存储器中的值之前。 谢谢。

最佳答案

在这种情况下,最好在 JLS 中查找:

17.7. Non-atomic Treatment of double and long :

For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.

Writes and reads of volatile long and double values are always atomic.

Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.

顺便说一句,“ volatile 字段会立即写入主内存,并且从主内存中进行读取”并不是真的。这是一种可能的实现方式,但 JVM 如何实际实现 volatile 提供的保证是它自己的决定。根据底层硬件的缓存一致性协议(protocol),还有其他更好的解决方案。

另一方面,可以想象,在某些低级硬件上保证这一点将涉及一些软件锁,以避免读/写损坏。效率低下?是的,但是如果 JVM 愿意的话,它完全可以自由地这样做。

关于java - 定义 long 或 double 变量时 volatile 关键字如何影响原子性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25070808/

相关文章:

java - Spark 将 JSON 字符串转换为 JSON 对象 (Java)

java - 什么是动态代理类,我为什么要使用一个?

JAVA SocketServer 带框架

pthreads 程序的竞争条件会使操作系统或 X 完全崩溃吗?

java - 防止mysql脏读

java - 通过 javascript 在下拉文本框中发送 key 的其他方式,因为它有时不起作用

java - "contextual lob creation"在JDBC中是什么意思?

android - 无法同步对 notify() 的调用

android - Android中的线程示例

java - 程序允许重复设置。怎么可能?