Reputation: 1739
I was wondering about singleton in enum and it's performance.
When we have multithreaded environment we have to synchronize moment, when an instance is created.
Simply, we can use synchronized mod, for function called getInstance() which create instance Somethink like that:
public synchronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
It's lazy implementation it's good for me. But synchronized method is slow. We can use double-locking to make it faster.
How about enum? When we implement singleton as enum, instance of singleton will be created as first use. Next use, return current instance.
How it works? When we want to get existing instance, there is implicit synchronized method which are slow? Or there is Double-lock implemented?
Upvotes: 4
Views: 919
Reputation: 298233
The initialization of enum
constants happens in the class initializer, similar to had you written
static final Singleton instance = new Singleton();
or
static final Singleton instance;
static {
instance = new Singleton();
}
The safety comes from the fact that the JVM perform class initialization under a JVM specific lock:
Because the Java programming language is multithreaded, initialization of a class or interface requires careful synchronization, since some other thread may be trying to initialize the same class or interface at the same time. … The implementation of the Java Virtual Machine is responsible for taking care of synchronization and recursive initialization by using the following procedure.
…
For each class or interface
C
, there is a unique initialization lockLC
. The mapping fromC
toLC
is left to the discretion of the Java Virtual Machine implementation.…
I left out a lot of technical details from the specification, as to a Java programmer, the most important point is that there is a safety mechanism implemented by every conforming JVM. The end of the section has the comment:
An implementation may optimize this procedure by eliding the lock acquisition in step 1 (and release in step 4/5) when it can determine that the initialization of the class has already completed, provided that, in terms of the memory model, all happens-before orderings that would exist if the lock were acquired, still exist when the optimization is performed.
This is, of course, an important point of this implementation of the singleton pattern, that later access to the static final
field does not need to acquire a lock. Since all classes go from the uninitialized to the initialized state exactly once and it affects every operation (including all other possibilities to implement the singleton pattern), you can expect every JVM to do this fundamental optimization. Even if a particular JVM does not do this, the static final
field would be the fastest lazy singleton implementation on that virtual machine…
Upvotes: 1
Reputation: 53535
Enum is thread-safe and is also the recommended way to implement a Singleton.
That said, enum is not lazily loaded. If you want a lazy-loaded singleton, you can use the Holder pattern (which is thread-safe as well):
class LazySingleton {
private LazySingleton() {}
private static class SingletonHelper{
private static final LazySingleton INSTANCE = new LazySingleton();
}
public static LazySingleton getInstance(){
return SingletonHelper.INSTANCE;
}
}
Upvotes: 3
Reputation: 38195
There is no lazy initialization with an enum
. It will simply create the instance when the class is loaded.
When we implement singleton as enum, instance of singleton will be created as first use.
That is only true if by "first use" you actually mean "when the class is loaded".
In other words, using your example, an enum would be equivalent to:
private static final Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
Upvotes: 1