Showing posts with label Double Checked Locking. Show all posts
Showing posts with label Double Checked Locking. Show all posts

Saturday, 10 August 2013

Double-checked locking Design Pattern-Out-of-order writes

Master Java Concurrency & Design Patterns!

Subscribe to Ram N Java for clear, beginner-friendly explanations of complex Java concepts.

👉 Subscribe Now on YouTube

Understanding the Out-of-Order Writes Issue

The Double-Checked Locking pattern is widely cited as an optimization technique for lazy-loading Singleton instances in multi-threaded environments. However, without careful handling, it can fail subtly due to a classic concurrency hazard known as out-of-order writes.

1. The Double-Checked Locking Setup

In a standard double-checked locking idiom, thread safety is attempted with two null checks and a synchronized block:

  • The first check verifies if the instance is null without taking a lock.
  • If null, the thread enters a synchronized block and checks once more.
  • If still null, it initializes the instance: instance = new Singleton();

2. What Happens During Object Creation?

When the line instance = new Singleton(); executes, the underlying JVM performs three distinct steps:

  1. Allocates memory space for the Singleton object.
  2. Executes the constructor to initialize fields inside that memory.
  3. Assigns the memory reference to the instance variable.

3. How Out-of-Order Writes Cause Bugs

Due to instruction reordering allowed by the Java Memory Model (JMM) for optimization:

  • Reordering: Step 3 can execute before Step 2. Memory is assigned to instance before constructor execution completes.
  • Thread Race: If Thread A allocates memory and publishes the reference, Thread B may arrive at the first null check.
  • Partially Initialized State: Thread B sees that instance is not null, skips synchronization, and immediately consumes the object—even though its fields are not yet initialized!

Because of this fundamental flaw under naive implementations, double-checked locking is often classified as an anti-pattern unless explicit memory-barrier guarantees (like the volatile modifier) are used.

Recommended Related Videos from Ram N Java

Deepen your multithreading and design pattern knowledge with these related tutorials:


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

Click the below Image to Enlarge
Double-checked locking Design Pattern-Out-of-order writes














See also:

  • All Design Patterns Links
  • 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
  • Thursday, 8 August 2013

    Double-checked locking Design Pattern - Introduction

    Master Java Multithreading & Architecture!

    Subscribe to Ram N Java for clean, step-by-step guides on core software engineering concepts.

    👉 Subscribe Now on YouTube

    What is the Double-Checked Locking Design Pattern?

    In software engineering, Double-Checked Locking (also referred to as Double-Checked Locking Optimization) is a concurrency pattern designed to reduce the overhead of acquiring a lock. It achieves this by testing the locking criterion prior to obtaining the lock, ensuring locking occurs only when strictly required.

    1. The Singleton Problem in Multithreaded Environments

    In a classic Singleton pattern, the constructor is private and a static getInstance() method ensures that only one instance of the class is created:

    • Single-Threaded Context: Checking if (instance == null) and lazily instantiating works smoothly without any issues.
    • Multi-Threaded Race Condition: If Thread A and Thread B call getInstance() simultaneously before the instance is initialized, both threads can evaluate the null check to true and create two separate instances, breaking the Singleton guarantee.

    2. Why Method-Level Synchronization is Inefficient

    A simple way to fix race conditions is adding the synchronized keyword to the getInstance() method. However, this creates a major performance bottleneck:

    • Synchronization is only truly needed the very first time the object is created.
    • Once the singleton instance exists, every subsequent call to getInstance() still pays the costly performance penalty of acquiring and releasing locks unnecessarily.

    3. The Double-Checked Locking Solution

    The Double-Checked Locking pattern resolves this inefficiency with a smarter check:

    1. Verify whether the instance is null without taking any lock.
    2. If it is already created, return the instance immediately with zero locking overhead.
    3. Only if the check indicates that the instance is null does the code enter a synchronized block and perform a second check before creating the object.

    Recommended Related Videos from Ram N Java

    Continue mastering concurrency and locking strategies with these tutorials:


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

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














    See also:

  • All Design Patterns Links
  • Tutorials