Please explain initialization safety as spelled out in Java memory model

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.


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).