Is writing a reference atomic on 64bit VMs
JavaReferenceAtomicMemory ModelJava Problem Overview
The java memory model mandates that writing a int
is atomic: That is, if you write a value to it (consisting of 4 bytes) in one thread and read it in another, you will get all bytes or none, but never 2 new bytes and 2 old bytes or such.
This is not guaranteed for long
. Here, writing 0x1122334455667788
to a variable holding 0
before could result in another thread reading 0x112233440000000
or 0x0000000055667788
.
Now the specification does not mandate object references to be either int or long-sized. For type safety reasons I suspect they are guaranteed to be written atomically, but on a 64bit VM these references could be very well 64bit values (merely memory addresses).
Now here are my questions:
- Are there any memory model specs covering this (that I haven't found)?
- Are long-writes suspect to be atomic on 64bit VMs?
- Are VMs forced to map references to 32bit?
Regards, Steffen
Java Solutions
Solution 1 - Java
Reading/writing references always atomic
See JLS section 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. > > Some implementations may find it convenient to divide a single write > action on a 64-bit long or double value into two write actions on > adjacent 32-bit values. For efficiency's sake, this behavior is > implementation-specific; an implementation of the Java Virtual Machine > is free to perform writes to long and double values atomically or in > two parts. > > Implementations of the Java Virtual Machine are encouraged to avoid > splitting 64-bit values where possible. Programmers are encouraged to > declare shared 64-bit values as volatile or synchronize their programs > correctly to avoid possible complications.
(Emphasis added)
AtomicReference
If you want to coordinate between old and new values, or want specific memory effects, use the class AtomicReference
.
For example, AtomicReference::getAndSet
returns the old value while setting the new value atomically, eliminating any chance of another thread having intervened between the two steps. Uses volatile
memory semantics.