Saturday, 10 August 2013

Double-checked locking Design Pattern - Implementation

Master Java Multithreading & Patterns!

Subscribe to Ram N Java for clean, beginner-friendly software architecture tutorials.

👉 Subscribe Now on YouTube

Implementing Double-Checked Locking in Java

Synchronizing an entire method call like getInstance() creates a performance bottleneck because every single thread has to acquire a lock, even after the singleton object has already been created. The Double-Checked Locking Design Pattern aims to solve this by acquiring the lock only when initialization is truly required.

1. The Implementation Structure

Instead of placing the synchronized keyword at the method level, synchronization is moved inside the method with two checks:

  • First Check: Verify if instance == null without locking. If it is already initialized, return it immediately without overhead.
  • Synchronized Block: If instance is null, enter a synchronized block to ensure only one thread can proceed.
  • Second Check: Check again if instance == null inside the synchronized block before allocating the object.

2. Step-by-Step Thread Execution Flow

Here is what happens when two threads (Thread A and Thread B) enter simultaneously:

  1. Thread A arrives: Evaluates instance == null (true) and acquires the lock on the synchronized block.
  2. Thread B arrives: Evaluates instance == null (true) and attempts to enter the synchronized block, but gets blocked because Thread A holds the lock.
  3. Thread A creates instance: Re-checks instance == null inside the block, initializes the new object, exits the synchronized block, and returns the reference.
  4. Thread B resumes: Enters the synchronized block, evaluates the second check instance == null (now false!), skips initialization, and safely returns the existing instance created by Thread A.

3. The Reality: Why It Can Fail

While the logic appears foolproof in theory, in practice it can break without proper memory barriers:

  • Out-of-Order Writes: The Java Memory Model allows compilers and processors to reorder instructions for performance. An object reference can be assigned before the constructor finishes executing.
  • Anti-Pattern Classification: Because unsynchronized reader threads can see partially initialized objects, double-checked locking is considered an anti-pattern unless used with the volatile keyword.

Recommended Related Videos from Ram N Java

Explore these multithreading tutorials to learn more about synchronization and locking:


Click here to watch in Youtube : https://www.youtube.com/watch?v=nL2n_NCl7TA

Click the below Image to Enlarge
Double-checked locking Design Pattern - Implementation














See also:

  • All Design Patterns Links
  • 1 comment:

    1. Thanks a lot. Nice explanation. One question. Threads born after instance is not Null will directly go to loc "return instance; " , but at same time there will be many threads(let us take Thread B) that are waiting for lock and after they get lock , they will run "if(instance==null)" and will go inside , if we don't use 'volatile' keyword for variable 'instance'. Am i correct here or else tell me where i am going wrong ?

      ReplyDelete

    Tutorials