Reputation: 1631
Static method and variable:
public class Singleton{
private static Singleton singleton = null;
private Singleton(){
}
public static synchronized Singleton getInstance(){
if(singletion == null)
singleton = new Singletion();
return singleton;
}
}
Second after Java 1.5
public class Singleton{
private static volatile Singleton singleton = null;
private Singleton(){
}
public static Singleton getInstance(){
if(singleton == null){
synchronized(this){
if(singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
So what's the pros and cons for these two thread safe code and when should we use which?
Upvotes: 1
Views: 690
Reputation: 58858
The first one is not thread safe. It would be thread safe if getInstance
was synchronized
.
If you need thread safety, use the second one.
There is a much simpler third way though, which is slightly different (the Singleton
gets created at a different time):
public class Singleton{
private static final Singleton singleton = new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return singleton;
}
}
Upvotes: -1
Reputation: 1757
The second one 'double checked' singleton is faster because it don't need to acquire lock whenever you ask for instance (despite first calls). Anyway best way to control life cycles of your objects is using dependency injection.
Upvotes: 0
Reputation: 50034
Both implementations are thread-safe and valid.
The former is shorter. It is more readable and maintainable.
The latter is faster, and it's also faster than most people think. Depending on the implementation of the Java VM, reading a volatile variable is as fast as reading a non-volatile variable on x86. That means the overhead occurs only during the initialaztion. But as soon as the singleton has been initialized, there is no overhead at all.
If performance is really an issue, you should use the latter. Otherwise use the former, because the need for readability and maintainability is often underestimated.
Upvotes: 3
Reputation: 17893
Both examples are of lazy initialization of singleton i.e. you initialize the singleton at the moment you need.The second example is an example of double checked locking which is primarily aimed at thread-safe.
Upvotes: 0
Reputation: 637
The safest way to go about doing a thread-safe singleton is via the initialisation on demand holder idiom:
public class Foo {
private Foo() {}
private static class Holder {
private static final Foo INSTANCE = new Foo();
}
public static Foo getInstance() {
return Holder.INSTANCE;
}
}
This works in Java versions that didn't properly support the volatile
keyword. The neat thing about this pattern is that it uses implicit locking only on the first access of getInstance
. After that, access is unsynchronized. This is due to a fun little quirk of memory management and static loading in Java.
Upvotes: 1
Reputation: 533492
The second is thread safe but the following is much simpler, and faster as it doesn't require a synchronized block.
public enum Singleton {
INSTANCE;
// define fields and methods here.
}
to access
Singleton.INSTANCE.method();
Note: an enum can implement an interface if you need.
Upvotes: 5