Any answer that does not explain in terms on java language specification is only partially correct, if correct at all.
You need to make a clear distinction between actions that happens within a single thread and are tied together by program order and that in turn creates a happens-before connection, specifically via:
If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).
That rule tells you that if you think about this code in single threaded world, it will always print 1
.
And on the other hand, actions that create synchronizes with connections across different threads, and implicitly those create happens-before, via:
If an action x synchronizes-with a following action y, then we also have hb(x, y).
In your case, I
is a plain field, as such every operation related to it is a plain store and/or a plain load. Such stores and loads do not created any connections at all according to the JLS
. As such some thread that reads I
can always read it as 0
if there is a writing thread involved.