java - double 和 long 的非原子处理

标签 java java.util.concurrent jls

Java Language Specification仅声明'write'操作被视为两部分:

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.

但书Java Concurrency In Practice states 'read' or 'write' 操作被视为两部分:

the JVM is permitted to treat a 64-bit read or write as two separate 32-bit operations.

哪个是准确的?

最佳答案

通过挖掘 JVM 规范的过去版本,有一个 interesting section来自 Java SE 6:

If a double or long variable is not declared volatile, then for the purposes of load, store, read, and write operations it is treated as if it were two variables of 32 bits each; wherever the rules require one of these operations, two such operations are performed, one for each 32-bit half. The manner in which the 64 bits of a double or long variable are encoded into two 32-bit quantities and the order of the operations on the halves of the variables are not defined by The Java Language Specification.

This matters only because a read or write of a double or long variable may be handled by an actual main memory as two 32-bit read or write operations that may be separated in time, with other operations coming between them. Consequently, if two threads concurrently assign distinct values to the same shared non-volatile double or long variable, a subsequent use of that variable may obtain a value that is not equal to either of the assigned values, but rather some implementation-dependent mixture of the two values.

An implementation is free to implement load, store, read, and write operations for double and long values as atomic 64-bit operations; in fact, this is strongly encouraged. The model divides them into 32-bit halves for the sake of currently popular microprocessors that fail to provide efficient atomic memory transactions on 64-bit quantities. It would have been simpler for the Java virtual machine to define all memory transactions on single variables as atomic; this more complex definition is a pragmatic concession to current hardware practice. In the future this concession may be eliminated. Meanwhile, programmers are cautioned to explicitly synchronize access to shared double and long variables.

此部分在以后的版本中不存在。我不想推测原因(尽管值得注意的是本节改编自 JLS 的第一版,而内存模型在 Java 5 中重新访问),但这与 JCIP 中描述的内容一致。

关于java - double 和 long 的非原子处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67935667/

相关文章:

java - Spring MVC - 通过 Thymeleaf 访问静态页面

java - Java 中的按键阻塞映射

Java:编译时解析和 "most specific method"

java - 在哪里可以找到 Class.getProtectionDomain().getCodeSource() 方法的规范?

java - 显示不正确修饰符的匿名内部类

java - 通过单击和取消单击 libgdx java 渲染多行

java - 找不到签名 key

java - 为什么 Java TreeMap 不打印所有插入的条目

java - 同时从列表中删除对象

java - 为什么ConcurrentHashMap$HashEntry中的 "next"字段是final的