Singleton - Double locking mechanism
Let us see the Singleton code which we use generally to create a singleton instance:
public static synchronized Singleton getInstance()
{
if (instance == null) //1
instance = new Singleton(); //2
return instance; //3
}
The code in Listing 2 works fine for multithreaded access to the getInstance() method. However, when you analyze it you realize that synchronization is required only for the first invocation of the method. Subsequent invocations do not require synchronization because the first invocation is the only invocation that executes the code at //2, which is the only line that requires synchronization. All other invocations determine that instance is non-null and return it. Multiple threads can safely execute concurrently on all invocations except the first. However, because the method is synchronized, you pay the cost of synchronization for every invocation of the method, even though it is only required on the first invocation.
In an effort to make this method more efficient, an idiom called double-checked locking was created. The idea is to avoid the costly synchronization for all invocations of the method except the first. So the new code would look like:-
public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) {
instance = new Singleton();
}
}
return instance;
}
Two threads can get inside of the if statement concurrently when instance is null. Then, one thread enters the synchronized block to initialize instance, while the other is blocked.
When the first thread exits the synchronized block, the waiting thread enters and creates another Singleton object. Note that when the second thread enters the synchronized block, it does not check to see if instance is non-null.Hence it will create more than single object of this singleton class. This is a problem. This is what called as "double-checked locking" .
To fix the problem we need a second check of instance. Like:-
public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
}
return instance;
}
public static synchronized Singleton getInstance()
{
if (instance == null) //1
instance = new Singleton(); //2
return instance; //3
}
The code in Listing 2 works fine for multithreaded access to the getInstance() method. However, when you analyze it you realize that synchronization is required only for the first invocation of the method. Subsequent invocations do not require synchronization because the first invocation is the only invocation that executes the code at //2, which is the only line that requires synchronization. All other invocations determine that instance is non-null and return it. Multiple threads can safely execute concurrently on all invocations except the first. However, because the method is synchronized, you pay the cost of synchronization for every invocation of the method, even though it is only required on the first invocation.
In an effort to make this method more efficient, an idiom called double-checked locking was created. The idea is to avoid the costly synchronization for all invocations of the method except the first. So the new code would look like:-
public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) {
instance = new Singleton();
}
}
return instance;
}
Two threads can get inside of the if statement concurrently when instance is null. Then, one thread enters the synchronized block to initialize instance, while the other is blocked.
When the first thread exits the synchronized block, the waiting thread enters and creates another Singleton object. Note that when the second thread enters the synchronized block, it does not check to see if instance is non-null.Hence it will create more than single object of this singleton class. This is a problem. This is what called as "double-checked locking" .
To fix the problem we need a second check of instance. Like:-
public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
}
return instance;
}
Comments