Both C# and Java define that
* volatile reads have acquire semantics
* volatile writes have release semantics
My questions are:
- Is this the only correct way to define volatile.
- If not, will things be awfully different if the semantics were reversed, that is
- volatile reads have release semantics
- volatile writes have acquire semantics
For Java, “volatile” tells the compiler that the value of a variable must never be cached as its value may change outside of the scope of the program itself.
By declaring the counter variable volatile all writes to the counter variable will be written back to main memory immediately. Also, all reads of the counter variable will be read directly from main memory. Declaring a variable volatile thus guarantees the visibility for other threads of writes to that variable.
volatile has semantics for memory visibility. Basically, the value of a volatile field becomes visible to all readers (other threads in particular) after a write operation completes on it. Without volatile , readers could see some non-updated value.
Volatile fields are instance or class (static) variables and are stored in the heap.
The reasoning behind the volatile
semantic is rooted in the Java Memory Model, which is specified in terms of actions:
The Java Memory Model defines a partial ordering called happens-before for the actions which can occur in a Java program. Normally there is no guarantee, that threads can see the results of each other actions.
Let's say you have two actions A and B. In order to guarantee, that a thread executing action B can see the results of action A, there must be a happens-before relationship between A and B. If not, the JVM is free to reorder them as it likes.
A program which is not correctly synchronized might have data races. A data race occurs, when a variable is read by > 1 threads and written by >= 1 thread(s), but the read and write actions are not ordered through the happens-before ordering.
Hence, a correctly synchronized program has no data races, and all actions within the program happen in a fixed order.
So actions are generally only partially ordered, but there is also a total order between:
These actions are totally ordered.
This makes it sensible to describe happens-before in terms of "subsequent" lock acquisitions and reads of volatile variables.
Regarding your questions:
volatile
This illustrates the happens-before relation when two threads synchronize using a common lock. All the actions within thread A are ordered by the program order rule, as are the actions within thread B. Because A releases lock M and B subsequently acquires M, all the actions in A before releasing the lock are therefore ordered before the actions in B after acquiring the lock. When two threads synchronize on different locks, we can't say anything about the ordering of actions between themthere is no happens-before relation between the actions in the two threads.
Source: Java Concurrency in Practice
The power of the acquire/release semantics isn't so much about how soon other threads see the newly written value of the volatile field itself, but rather in the way volatile operations establish a happens-before relation across different threads. If a thread A reads a volatile field and sees a value that was written to that field in another thread B then thread A is also guaranteed to see values written to other (not necessarily volatile) variables by thread B before the point where it did the volatile write. This looks like cache flushing but only from the point of view of a thread that read the volatile, other threads that don't touch the volatile field have no ordering guarantees with respect to B and might see some of its earlier non-volatile writes but not others if the compiler/JIT is so inclined.
Monitor acquires/releases are similarly characterised by their induced happens-before relation - actions by one thread before a release of a monitor are guaranteed to be visible after a subsequent acquire of the same monitor by another thread. Volatiles give you the same ordering guarantees as monitor synchronisation but without blocking.
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