简体   繁体   中英

Non-Atomic Treatment of double and long

The Java Language Specification states only 'write' operation is treated as two parts:

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.

But the book Java Concurrency In Practice states 'read' or 'write' operation is treated as two parts:

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

Which one is accurate?

Digging through the past editions of the JVM spec, there is an interesting section from 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.

This section is not present in later releases. I don't want to speculate on why (although it's worth noting that this section was adapted from the first edition of the JLS, while the memory model was revisited in Java 5), but this goes with what is described in JCIP.

It's both reads and writes. It can not be otherwise. Think about it, what if you code on ARM with 32 bits (like a phone, for example). While a thread does a write to a long , a reader (unless you mark that long with volatile ) is allowed to see a torn value. It happens simply because the architecture does not have a 64-bit register to update the value atomically.

On x86 that is easily achieved, of course, since it has 64 bit registers. But even there, a value can be "with one foot" on one cache line, and "with other foot" on another cache line. So when someone updates the first cache line (but not the second), you could be into a surprise. The VM as such aligns 64 bit values onto a power of two off-set all the time (and a multiple of 8 ). For example a class like:

static class Example {
    long x = 42;
}

is going to be aligned as:

 Layout$Example object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                              
     0    12        (object header)                           
    12     4        (alignment/padding gap)                  
    16     8        long Example.x                                 

that is: there is a 4 bytes gap (padding) between the headers and the actual value of x so that it is aligned. This makes sure that x is not going to end up on two cache lines.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM