I think reading 0 is possible.
The spec says:
A write to a volatile variable v
synchronizes-with all subsequent reads of v
by any thread (where "subsequent" is defined according to the synchronization order).
In our case, we have a write and a read of the same variable, but there is nothing that ensures the read to be subsequent. In particular, the write and read occur in different threads that are not related by any other synchronization action.
That is, it is possible that the read will occur before the write in synchronization order.
This may sound surprising given that the writing thread writes f
after y
, and the reading thread reads y
only if it detects f
has been written. But since the write and read to f
are not synchronized, the following quote applies:
More specifically, if two actions share a happens-before relationship, they do not necessarily have to appear to have happened in that order to any code with which they do not share a happens-before relationship. Writes in one thread that are in a data race with reads in another thread may, for example, appear to occur out of order to those reads.
The explanatory notes to example 17.4.1 also reaffirm that the runtime is permitted to reorder these writes:
If some execution exhibited this behavior, then we would know that instruction 4 came before instruction 1, which came before instruction 2, which came before instruction 3, which came before instruction 4. This is, on the face of it, absurd.
However, compilers are allowed to reorder the instructions in either thread, when this does not affect the execution of that thread in isolation.
In our case, the behavior of the writing thread, in isolation, is not affected by reordering the writes to f
and y
.
volatile
guarantees that all actions (reads and writes) that happen before the write to thevolatile
are visible.final
guarantees that only that particular field (and any object the field refers to) is visible.final
is called out explicitly to NOT have a transitive relationship with all other actions on a thread. (So, previous reads and writes on a thread are unaffected by afinal
field.) – Arsonistfinal
means the value (which can be a reference) is assigned exactly once, and assignment happens during object initialization - it may never be reassigned.final
has nothing to do with visibility. – Delilafinal
keyword. – Arsonistfinal
is for initialization andvolatile
is about updating the variable at the same. – Finicalfinal
doesn't needvolatile
because its value never changes, but that has nothing to do with visibility. Are you still sure "I'm 100% wrong"? – Delilavolatile
andfinal
. It's one or the other. And happens-before means "visible" in the JLS. You need to read that entire chapter for it to make sense: JLS section 17.4.5. Happens-before Order "Two actions can be ordered by a happens-before relationship. If one action happens-before another, then the first is visible to and ordered before the second." I'm not really interested in spoon feeding this to you. Please make an effort on your own, or at least ask a question here that someone can answer. @Delila – Arsonisty
can be 0 even ifvolatile
. Something I was not aware of, and seems to be a subtle point in the Java memory model. – Arsonistfinal
in the spec, are for all fields, your example violates that. But it is very tricky, I agree. Although I really like these things, I sometimes get them wrong too. – Satterwhite