I have found in this site some interesting questions (e.g. this one) about the visibility effects of volatile variables in Java originated from this paragraph taken from the book Java concurrency in Practice:
The visibility effects of volatile variables extend beyond the value of the volatile variable itself. When thread A writes to a volatile variable and subsequently thread B reads that same variable, the values of all variables that were visible to A prior to writing to the volatile variable become visible to B after reading the volatile variable. So from a memory visibility perspective, writing a volatile variable is like exiting a synchronized block and reading a volatile variable is like entering a synchronized block.
There is, however, an scenario that is not completely clear for me even after reading the answers to related questions in this site, concretely:
A0
writing to the same volatile variable before the thread A
?In other words: A0
writes the volatile variable, this value is later overwritten by A
(which does not read the variable) and afterwards read by B
, so we have two write operations from different threads (A0
and A
) and a read operation from a third thread (B
).
Can I safely assume that both A
and B
are guaranteed to see everything that was visible to A0
before A0
wrote to the volatile variable?
This is a conceptual question about the Java memory model.
I know that I cannot predict the order in which writes to the volatile variable occurs in threads A0
and A
and the read in thread B
.
However, just for the sake of facilitating the discussion, let's say that A0
starts lots of time before A
does it, and after another significant amount of time B
starts, and let's make the simplifying assumption that this is enough to guarantee that the writes and reads happen in the described order (I know that the order cannot be guaranteed by timing only, this is just a simplification in order to avoid diverging from the original question).
Can I safely assume that both A and B are guaranteed to see everything that was visible to A0 before A0 wrote to the volatile variable?
Writing to a volatile doesn't give a thread any happens-before guarantees about reads.
When B
reads, it will see anything A0 could see provided it sees the update it makes. B
can also see anything A
could see provided it sees the value A
wrote. Otherwise B
could see state older than either thread if the value it reads didn't come from that thread i.e. it was too early.
If A0
attempts to write first, it might complete after A
e.g. say A
is on the same socket as the clean copy of the data. It can get access to it before A0
as the later will take longer to acquire the cache line. It is the one which finishes last which determines the eventual state of the data.