private volatile static Singleton uniqueInstance
In a singleton when using double lock method for synchronization why is the single instance declared as volatile ? Can I achieve the same functionality without declaring it as volatile ?
This double check lock is only necessary if you are worried about many threads calling the singleton simultaneously, or the cost of obtaining a lock in general. Its purpose is to prevent unnecessary synchronization, thereby keeping your code fast in a multi-threaded environment.
Since it requires the volatile keyword to work properly, it's not compatible with Java 1.4 and lower versions. The problem is that an out-of-order write may allow the instance reference to be returned before the singleton constructor is executed. Performance issue because of decline cache for volatile variable.
Double checked locking of Singleton is a way to make sure that only one instance of Singleton class is created through an application life cycle.
Thread Safe Singleton in JavaCreate the private constructor to avoid any new object creation with new operator. Declare a private static instance of the same class. Provide a public static method that will return the singleton class instance variable.
The volatile
prevents memory writes from being re-ordered, making it impossible for other threads to read uninitialized fields of your singleton through the singleton's pointer.
Consider this situation: thread A discovers that uniqueInstance == null
, locks, confirms that it's still null
, and calls singleton's constructor. The constructor makes a write into member XYZ
inside Singleton, and returns. Thread A now writes the reference to the newly created singleton into uniqueInstance
, and gets ready to release its lock.
Just as thread A gets ready to release its lock, thread B comes along, and discovers that uniqueInstance
is not null
. Thread B
accesses uniqueInstance.XYZ
thinking that it has been initialized, but because the CPU has reordered writes, the data that thread A has written into XYZ
has not been made visible to thread B. Therefore, thread B sees an incorrect value inside XYZ
, which is wrong.
When you mark uniqueInstance
volatile, a memory barrier is inserted. All writes initiated prior to that of uniqueInstance
will be completed before the uniqueInstance
is modified, preventing the reordering situation described above.
Without volatile
the code doesn't work correctly with multiple threads.
From Wikipedia's Double-checked locking:
As of J2SE 5.0, this problem has been fixed. The volatile keyword now ensures that multiple threads handle the singleton instance correctly. This new idiom is described in The "Double-Checked Locking is Broken" Declaration:
// Works with acquire/release semantics for volatile // Broken under Java 1.4 and earlier semantics for volatile class Foo { private volatile Helper helper = null; public Helper getHelper() { Helper result = helper; if (result == null) { synchronized(this) { result = helper; if (result == null) { helper = result = new Helper(); } } } return result; } // other functions and members... }
In general you should avoid double-check locking if possible, as it is difficult to get right and if you get it wrong it can be difficult to find the error. Try this simpler approach instead:
If the helper object is static (one per class loader), an alternative is the initialization on demand holder idiom
// Correct lazy initialization in Java @ThreadSafe class Foo { private static class HelperHolder { public static Helper helper = new Helper(); } public static Helper getHelper() { return HelperHolder.helper; } }
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