Initialization safety provides for an object to be seen by an external thread in its fully constructed (initialized) state. The prerequisite is that the object should not be published prematurely ie. in its constructor. Once this is ensured, JMM requires certain behavior for the fields that are declared as final
. First, all final
object fields are guaranteed to be seen by an external thread in its fully initialized state. This is not as trivial as it sounds.
Consider a class:
class A {
List list;
A() {
list = Arrays.asList(some init expressions that adds 10 elements to list);
}
}
A thread that accesses the list
of A's
instance is not by default guaranteed to see 10 elements in that list. In fact, this thread can even see list
as null
. However, if list
is declared final
, then, as required by JMM, the list
must always appear to be initialized with 10 elements in it.
Secondly, this initialization guarantee is not limited to the final
field itself but is extended recursively to all objects referred by it. For example, if the list
in the above example is a list of lists themselves, then the external thread is guaranteed to see the inner lists as fully initialized.
Note that nowhere are we using synchronized
to achieve this safety in memory visibility (happens-before relationship).
1. Initialization safety allows properly constructed immutable objects to be shared safely across threads without using synchronization, irrespective of even if they published using a data race.
2. Objects having final field, initialization safety prevent reordering any part of construction with the initial load of a reference to that object.
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