Implies having at most single instance of a class.
Need:Singleton provides global way to access resources. Suppose we have a centralize configuration data to be used across the application, more than one instance of configuration data will result in incorrect behaviour of application. There are other examples as well when we need singleton mainly, thread pools, caches etc.
Ways to create:
class IAmSingleton{
private static IAmSingleton singletonRef;
public static IAmSingleton getInstance(){
if(singletonRef ==null)
return singletonRef = new IAmSingleton(); //line 1
else
return singletonRef ;
}
private IAmSingleton(){}
}
What if two threads are at line 1, two instances will be created. To stop this lets syncronize getInstance().
Synchronization come with cost of performance loss. Lets see how can we achieve single instance in multi threading environment with less impact.
If the object desired to behave as singleton is less resource incentive, we can go for pre loading the class(instance of class will be created at the class loading time).
class IAmSingleton{
private static IAmSingleton singletonRef = new IAmSingleton();
private IAmSingleton(){}
}
But if its resource incentive we can try to improve our synchronization logic. Lets see how..
class IAmSingleton{
private static volatile IAmSingleton singletonRef ;
public static IAmSingleton getInstance(){
if (singletonRef ==nulll)
syncronize (IAmSingleton.class){
if (singletonRef == null)
return new IAmSingleton();
else
return singletonRef ;
}
}
else
return singletonRef ;
}
privateIAmSingleton(){}
}
The advantage the above code will provide is, synchronized block will not be executed once value is assigned to singleton ref. This strategy is known as double check locking(double check locking doesn't work pre 1.5 JDK).
I feel the code above needs some modofications like
ReplyDeleteclass IAmSingleton{
private static volatile IAmSingleton singletonRef ;
public static IAmSingleton getInstance(){
if (singletonRef ==null)
syncronize (IAmSingleton.class){
return new IAmSingleton();
}
}
else
return singletonRef ;
}
privateIAmSingleton(){}
}
This will avoid the double check because when thread1 is inside the synchronized block it already has the lock on the singleton instance and need not bother about thread 2.So when it has already passed the null check no need to check it again
Anyway a nice post
ReplyDeleteGood question. Let me explain this.
ReplyDeleteif (singletonRef ==null)
syncronize (IAmSingleton.class){//1
return new IAmSingleton();
}
}
else
return singletonRef ;
}
Suppose there are two threads at line 1. One of them will go inside the synchronized block and create the instance. As we know synchronization has two aspects first it will not allow multiple access to shared resource to maintain integrity of shared data secondly once a thread goes inside or come out of synchronized block it updates latest value to the shared data. In our case once thread one will go out of synchronized block it will update singletonRef as not null. Since second thread is at line 1 so it will go inside synchronized block and create another instance of singleton object. That's why double check is needed. In case of double check once the thread go inside synchronized block it will get the updated data which is not null for singletonRef and second null check will fail. So instead of creating another instance it will return the reference of existing instance.
Looking forward to have more comments/ question from you. Thx.
class Singleton {
ReplyDeleteprivate static final Singleton SINGLETON = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return SINGLETON;
}
}
I think that's the best implementation for a singleton. The key is in the fact that SINGLETON is final.