1

Regarding a previous question I raised,

    public static Singleton getInstanceDC() {
    if (_instance == null) {                // Single Checked (1)
        synchronized (Singleton.class) {
            if (_instance == null) {        // Double checked (2)
                _instance = new Singleton();
            }
        }
    }
    return _instance;

}

Why should I use the second instance null check condition. What possible effect could it have?

Community
  • 1
  • 1
jayendra bhatt
  • 1,337
  • 2
  • 19
  • 41

1 Answers1

4

Let's number lines so we can see how threads might interleave operations.

if (_instance == null) {                // L1
    synchronized (Singleton.class) {    // L2
        if (_instance == null) {        // L3
            _instance = new Singleton();// L4
        }
    }
}

Let's consider an interleaving without the check on L3.

  1. Thread 1 reaches L1 and _instance is null
  2. Thread 2 reaches L1 and _instance is null
  3. Thread 1 obtains mutex at L2
  4. Thread 2 tries to obtain mutex at L2 but blocks
  5. Thread 1 creates new instance and assigns at L4
  6. Thread 1 releases mutex from L2
  7. Thread 2 obtains mutex at L2
  8. Thread 2 creates new instance and assigns at L4
  9. Thread 2 releases mutex from L2

Two instances were created of Singleton. Each thread returns its own instance.

With the check at L3, step 8 doesn't happen because at step 7 thread 2's view of _instance was synced with thread 1's, so only one instance of Singleton is created.

Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • My multithreading is pretty rusty, but can't we just make the whole method synchronized and remove the extra check inside the method? – turingcomplete Oct 30 '15 at 03:32
  • 2
    You can do that but would mean getting a lock even when the object was already created, so it is not going to be efficient. With double check we ensure that if the object is already created you don't have to wait (for the lock) to get it. – User2709 Oct 30 '15 at 03:50
  • 1
    @turingcomplete, You can use the [inner class](https://en.wikipedia.org/wiki/Singleton_pattern#Initialization-on-demand_holder_idiom) solution to avoid locking per fetch and instead rely on the locking implicit in the class loader which is removed by code rewriting after a successful load. – Mike Samuel Oct 30 '15 at 13:52