0

New to Java from C++ and came across this synchronized block example (more context on this page). My question is:
Shouldn't the "if" statement also be included in the "synchronized block"? Or else other threads could be executing the same piece of code, pass the "if" checkpoint and thought that the "_instance" is null and then after the current thread finishes executing the synchronized block (and creates a new instance), other thread(s) will create duplicated instances? Thanks!

Now I realized that the code was actually doing double-checking, I have a new question then, why is double-checking needed? Thanks!

The code block is copied below:

public class Singleton{ 
private static volatile Singleton _instance; 
public static Singleton getInstance(){
    if(_instance == null){ //Shouldn't this line be included in the synchronized block?
        synchronized(Singleton.class){
            if(_instance == null) _instance = new Singleton(); 
        }
    } 
    return _instance; 
}
Vasu
  • 21,832
  • 11
  • 51
  • 67
FengC
  • 11
  • 3
  • This is a poor approach for creating a lazy singleton. The [initialization on demand idiom](https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom) is far cleaner. – Andy Turner Apr 16 '17 at 21:24
  • Related: http://stackoverflow.com/questions/7855700/why-is-volatile-used-in-this-example-of-double-checked-locking – John Bollinger Apr 16 '17 at 21:24
  • If you have a new question, pose it in a separate question. But before you do so, you should try performing your own research. Now that you have a name for what you're looking at, that shouldn't be hard. – John Bollinger Apr 16 '17 at 21:26

1 Answers1

0

If you include the statement _instance == null inside the synchronized block it will add unnecessary overhead (getting lock and realising the lock) for each request/call made to the getInstance() method i.e., you will only acquire/release the lock (on the Singleton object) only when you know that the object has not been created, so there is no need to unnecessarily get the lock and check if it is not null already.

Why is double-checking needed?

Assume that you are doing the check only once like below:

public static Singleton getInstance(){
    synchronized(Singleton.class){
         if(_instance == null) //SINGLE IF CHECK
            _instance = new Singleton(); 
    }
    return _instance; 
}

Now the issue is that the code will need to acquire/release the lock (on the Singleton class) for each call made to the method, which is not required because once the Singleton instance (using new Singleton()) has been created during the first call to the method, it is _instance is not going to be null. So, by adding the additional condition _instance == null above synchronized, it will avoid the unnecessary locking overhead for each call afterward, this concept is well known as double-checked locking.

I suggest you also read here (text copied below, emphasis mine) and also read duplicate link to understand this concept better.

The double-checked locking idiom is a software design pattern used to reduce the overhead of acquiring a lock by first testing the locking criterion without actually acquiring the lock. Double-checked locking improves performance by limiting synchronization to the rare case of computing the field's value or constructing a new instance for the field to reference and by foregoing synchronization during the common case of retrieving an already-created instance or value.

Community
  • 1
  • 1
Vasu
  • 21,832
  • 11
  • 51
  • 67
  • 2
    @efekctive and for good reason. I suggest you read the duplicate too, as you clearly don't understand the DCL idiom. – Kayaman Apr 16 '17 at 21:24