Master Java Multithreading & Patterns!
Subscribe to Ram N Java for clean, beginner-friendly software architecture tutorials.
👉 Subscribe Now on YouTubeImplementing 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 == nullwithout locking. If it is already initialized, return it immediately without overhead. - Synchronized Block: If
instanceis null, enter asynchronizedblock to ensure only one thread can proceed. - Second Check: Check again if
instance == nullinside 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:
-
Thread A arrives: Evaluates
instance == null(true) and acquires the lock on the synchronized block. -
Thread B arrives: Evaluates
instance == null(true) and attempts to enter the synchronized block, but gets blocked because Thread A holds the lock. -
Thread A creates instance: Re-checks
instance == nullinside the block, initializes the new object, exits the synchronized block, and returns the reference. -
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
volatilekeyword.
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
| Double-checked locking Design Pattern - Implementation |
See also:
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