Are multiple threads guaranteed to see the same version of a shared local variable in their scope.
In general, it depends on what you mean by "the same version". It also depends on the nature of the variable (e.g. how it is declared and initialized) ... and on how the threads use it.
(In general, Java doesn't do "versions" of variables. A thread accessing a shared variable or object will either see the latest state, or it won't. If it sees a state that isn't the latest state, then there are no guarantees as to what it will see. In particular, it may see something that doesn't directly correspond to any notional version of the object ... due to word-tearing and other cache-related memory artefacts.)
In your example you are using a final
local variable within an inner class (in this case you have two anonymous inner classes). When you do that, the compiler creates a corresponding synthetic variable in the inner class that is initialized with the value of the variable in the method scope. The compiled inner class then refers to the value of the synthetic variable instead of the original variable.
In your example, it is guaranteed that the inner classes (e.g. your threads) will see the same (reference) value as in the original variable. Furthermore, it is guaranteed that they will (at least initially) see a consistent snapshot of whatever object it is that it references. (And since it is an AtomicXxxx
class, it will always be consistent for all threads that can access it. Guaranteed.)
OK, so what about other cases:
If flag
was a static or instance field that was also final
, then we wouldn't have synthetic variables, and each nested class would be referencing the same shared variable. But it would all still work.
If flag
was a static or instance field and it wasn't final
, but nothing changed the field (after creating of the threads) then it would still be OK. (Though you could argue that this is fragile ... because something could change the field.)
If flag
was a static or instance field and it wasn't final
or volatile
, then the threads would initially see the same state as the parent thread. But if either the original thread or any of the other threads changed the variable (etcetera), then the others are not guaranteed to see the new state ... unless they respective threads synchronize properly.
I would like to know if changes to flag made in one thread are seen immediately by the other two threads.
As I said above, it depends ...
In your example, the answer is "yes", because you use a final
reference to AtomicBoolean
.
If you had declared flag
as a boolean
and marked it as volatile
, then the answer would be "yes".
If you had declared flag
as a boolean
and non-volatile, then the answer would be "no".
If flag
was a final
reference to an ordinary object with a mutable non-volatile boolean
field, then the answer would also be "no". (The threads would all see the same object, but they wouldn't consistently see the latest state. The solution would be to use synchronized getters and setters, or equivalent.)