Yes, you need to synchronize accesses to the elements of a volatile array.
Other folks have already addressed how you can probably use CopyOnWriteArrayList
or AtomicReferenceArray
instead, so I'm going to veer off into a slightly different direction. I'd also recommend reading Volatile Arrays in Java by one of the big JMM contributors, Jeremy Manson.
Now, I can gurantee that the only one thread (call it writer) can write to the array as e.g. follows:
Whether you can give single writer guarantees or not is not in any way related to the volatile
keyword. I think you didn't have that in mind, but I'm just clarifying, so that other readers don't get the wrong impression (I think there's a data race pun that can be made with that sentence).
All other threads will only read values written by the writer thread.
Yes, but like your intuition correctly lead you, this holds only for the value of the reference to the array.
This means that unless you are writing array references to the volatile
variable, you won't get the write part of the volatile
write-read contract.
What this means is that either you want to do something like
objects[i] = newObj;
objects = objects;
which is ugly and awful in many different ways.
Or you want to publish a brand new array each time your writer makes an update, e.g.
Object[] newObjects = new Object[100];
// populate values in newObjects, make sure that newObjects IS NOT published yet
// publish newObjects through the volatile variable
objects = newObjects;
which is not a very common use-case.
Notice that unlike setting array elements, which does not provide volatile
-write semantics, getting array elements (with newObj = objects[i];
) does provide volatile
-read semantics, because you are dereferencing the array :)
Because it would not be useful from performance standpoint if JVM provides some kind of memory consistency guarantess when writing to an array. But I'm not sure about that.
Like you're alluding, ensuring the memory fencing required for volatile
semantics will be very costly, and if you add false sharing to the mix, it becomes even worse.
Didn't find anything helpful in documentation.
You can safely assume then that the volatile
semantics for array references are exactly the same as the volatile
semantics for non-array references, which is not surprising at all, considering how arrays (even primitive ones) are still objects.