From the book Effective Java:
While the volatile modifier performs no mutual exclusion, it guarantees that any thread that reads the field will see the most recently written value
SO and many other sources claim similar things.
Is this true?
I mean really true, not a close-enough model, or true only on x86, or only in Oracle JVMs, or some definition of "most recently written" that's not the standard English interpretation...
Other sources (SO example) have said that volatile in Java is like acquire/release semantics in C++. Which I think do not offer the guarantee from the quote.
I found that in the JLS 17.4.4 it says "A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where "subsequent" is defined according to the synchronization order)." But I don't quite understand.
There are quite some sources for and against this, so I'm hoping the answer is able to convince that many of those (on either side) are indeed wrong - for example reference or spec, or counter-example code.
The volatile keyword is useful in two multi-threading scenarios: When only one thread writes to the volatile variable and other threads read its value. Thus, the reading threads see the latest value of the variable.
It guarantees that value of the volatile variable will always be read from the main memory, not from the local thread cache. It reduces the risk of memory consistency error. Any write to volatile variable in Java establishes a happen before the relationship with successive reads of that same variable.
The volatile keyword means that the compiler will force a new read of the variable every time it is referenced. This is useful when that variable is something other than standard memory.
If you write volatile variable from multiple threads without using any synchronized constructs, you are bound to get data inconsistency errors.
System. Threading Volatile. Read Method System. Threading Reads the value of a field. On systems that require it, inserts a memory barrier that prevents the processor from reordering memory operations as follows: If a read or write appears after this method in the code, the processor cannot move it before this method.
Unlike synchronized methods or blocks, it does not make other threads wait while one thread is working on a critical section. Therefore, the volatile keyword does not provide thread safety when non-atomic operations or composite operations are performed on shared variables. Operations like increment and decrement are composite operations.
The volatile keyword is useful in two multi-threading scenarios: When only one thread writes to the volatile variable and other threads read its value. Thus, the reading threads see the latest value of the variable. When multiple threads are writing to a shared variable such that the operation is atomic.
In this article, we saw that declaring a shared variable as volatile will not always be thread-safe. We learned that to provide thread safety and avoid race conditions for non-atomic operations, using synchronized methods or blocks or atomic variables are both viable solutions.
Is this true?
I mean really true, not a close-enough model, or true only on x86, or only in Oracle JVMs, or some definition of "most recently written" that's not the standard English interpretation...
Yes, at least in the sense that a correct implementation of Java gives you this guarantee.
Unless you are using some exotic, experimental Java compiler/JVM (*), you can essentially take this as true.
From JLS 17.4.5:
A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.
(*) As Stephen C points out, such an exotic implementation that doesn't implement the memory model semantics described in the language spec can't usefully (or even legally) be described as "Java".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With