The object creation operation in Java is not atomic.
Consider ( one of the possible ) an example with the operation of creating an object and two threads:
Поток A enters the getInstance() method, at this point in time, instance == null and it enters a synchronized block, in which instance == null also starts creating a Singleton object. First, memory is allocated for an object, then this object is initialized with a reference to the allocated memory area. At this point in time, Поток B enters the getInstance() method and sees that instance != null and begins to use an already existing, but not yet ground, constructed object (since its fields have not yet been initialized).
Declaring the instance field as volatile ( JDK 5+ ) sets the happens before relationship between initializing the object of instance Потоком A and returning the object of instance Потоку B
In other words, declaring an instance field as volatile ensures that поток В reads a fully constructed instance object.
UPD. From @Roman comments , another reason for using volatile :
Without volatile there is another problem: if the first if (instance == null) check does not see null , the subsequent return instance can see null , as a result, the method returns null .
If there is no correct synchronization, the reading that goes "later" can see the value that was "earlier", because JMM does not prohibit reordering such readings.
A variable declared volatile is never cached into the memory of the thread, that is, it will have the same ( actual ) value at any time in any thread (if one thread changes its value, then this value is immediately available in other threads).
volatileand even know about the processor cache. The question is, why should we make theinstanceprotected from caching, if the second check occurs inside the locked monitor? - faoxis