I'm still not 100% sure about this and I'd like some input. When you read about the volatile keyword semantics you learn about its visibility effects. You also learn that volatile does not provide atomicity, but this observation is always made in the context of compound actions: you can't make n actions transactional using volatile like you can do so with synchronized.
But does volatile give us read-write atomicity too, or should it only be used with types that inherently have this property like boolean? (which means some variables are read-write atomic, and some others aren't, like 64 bit values I think)
I'd say it yes does, that is, volatile applied to any variable type makes that variable read and write atomic. The reason I think this is because in order to ensure visibility, volatile must establish the happens-before relationship between thread A writing to the volatile and other threads subsequently reading from it, which is the very definition of atomicity :
Operations A and B are atomic with respect to each other if, from the perspective of a thread executing A, when
another thread executes B, either all of B has executed or none of it has. An atomic operation is one that is atomic with
respect to all operations, including itself, that operate on the same state. - Java Concurrency in Practice.
To put it simply, I want to know if a write to a volatile variable, no matter what it's type, can happen concurrently or not.
There is one and only one rule for volatile variables: "A write to a volatile field happens-before every subsequent read of that same field."
This is it. It only guarantees that the reader will always see actual value of the variable in case it is performed after write from another thread.
There is no word about writer-wirter collaboration.
It only guarantees that the reader will always see actual value of the variable in case
Strictly it guarantees more , pre JSR 133 this was true, post new memory model it guarantees effectively the same as a monitor release and establishes happens before order such that non volatile writes pre the volatile write have happened effectively for the volatile reader. It's not just an effective cache flush of a 32 bit value. This is particularly important when you consider things like the double checked locking idiom ... http://en.wikipedia.org/wiki/Double-checked_locking
Better explanation here under ... What does volatile do
On a 32 bit JVM, all read or writes (single load or store) are almost always atomic -- the exceptions for longs and doubles. On a 64 bit JVM, there are no exceptions.
With volatile, a few things changes. The variable won't be cached. The memory model will restrict what the JVM can do with the load and store ordering. And finally, on a 32 bit JVM, load or store, for longs and doubles, are now guaranteed to be atomic. For this last case, the JVM will use an internal lock to make that guarantee.
Henry Wong wrote:With volatile [...] on a 32 bit JVM, load or store, for longs and doubles, are now guaranteed to be atomic. For this last case, the JVM will use an internal lock to make that guarantee.
To be fair, this was always "guaranteed" according to the JLS. It just didn't actually work reliably until JDK 5 or so. I think they may have back-ported a fix into 1.4 as well.