Search code examples
javasingletonvolatilethread-synchronizationdouble-checked-locking

What is the point of making the singleton instance volatile while using double lock?


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 ?


Solution

  • 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;
        }
    }