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
orlong
variable is not declaredvolatile
, 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 adouble
orlong
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
orlong
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
orlong
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
andlong
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 shareddouble
andlong
variables.
此部分在以后的版本中不存在。我不想推测原因(尽管值得注意的是本节改编自 JLS 的第一版,而内存模型在 Java 5 中重新访问),但这与 JCIP 中描述的内容一致。
关于java - double 和 long 的非原子处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67935667/