Subject: What we can learn from Singleton Pattern -- Code Efficiency
Author: Alex_Raj
In response to: What we can learn from Singleton Pattern -- Concurrent Access Issue
Posted on: 12/05/2013 11:39:46 PM
What's wrong with the example shown above this time? Nothing is wrong here, but it's just not efficient.
You might have noticed the cost of synchronization -- there will be an extra cycle to grab and release the sync lock each time to get the instance. Only the first time is really needed and the rest are just pure waste of time.
Here comes the variation to enter the sync block only once:
/**
* Synchronized on block - double-checked locking
*/
public class Singleton
{
/* static field to ensure only one copy */
private static Singleton instance;
/* private constructor to prevent it from being instantiated from outside */
private Singleton() {
}
/* public static method to ensure global point of access */
public static Singleton getInstance()
{
if(instance==null){
synchronized(Singleton.class){
if(instance==null){
instance = new Singleton();
}
}
}
return instance;
}
public void sayHello() {
System.out.println("Hello");
}
}
>
> On 12/05/2013 11:32:16 PM
Alex_Raj wrote:
What's wrong with the example shown above? Yes, it's not thread-safe.
The singleton pattern must be carefully constructed in multi-threaded applications. If two threads are to execute the creation method at the same time when a singleton does not yet exist, they both end up with creating their own instances -- which contradicts the definition or purpose of singleton at the first place. Moreover, if the creation of singleton involves grabbing a mutual exclusive resource (e.g. disk file holder or database connection), the second instance of the singleton may either gets blocked or holds a null reference to the underlying resource.
There is the thread-safe version:
/**
* Synchronized on method getInstance()
*/
public class Singleton
{
/* static field to ensure only one copy */
private static Singleton instance;
/* private constructor to prevent it from being instantiated from outside */
private Singleton() {
}
/* public static method to ensure global point of access */
public static synchronized Singleton getInstance()
{
if(instance==null){
instance = new Singleton();
}
return instance;
}
public void sayHello() {
System.out.println("Hello");
}
}
OR
/**
* Synchronized on block
*/
public class Singleton
{
/* static field to ensure only one copy */
private static Singleton instance;
/* private constructor to prevent it from being instantiated from outside */
private Singleton() {
}
/* public static method to ensure global point of access */
public static Singleton getInstance()
{
synchronized(Singleton.class){
if(instance==null){
instance = new Singleton();
}
}
return instance;
}
public void sayHello() {
System.out.println("Hello");
}
}
References: