Why use double checked locking
Asked Answered
K

1

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?

Keyboard answered 30/10, 2015 at 3:3 Comment(0)
H
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.

Heritable answered 30/10, 2015 at 3:27 Comment(3)
My multithreading is pretty rusty, but can't we just make the whole method synchronized and remove the extra check inside the method?Ysabel
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.Beulahbeuthel
@turingcomplete, You can use the inner class 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.Heritable

© 2022 - 2024 — McMap. All rights reserved.