Singleton & Multithreading in Java
You need synchronization inside getInstance
only if you initialize your singleton lazily. If you could create an instance before the threads are started, you can drop synchronization in the getter, because the reference becomes immutable. Of course if the singleton object itself is mutable, you would need to synchronize its methods which access information that can be changed concurrently.
If you're talking about threadsafe, lazy initialization of the singleton, here is a cool code pattern to use that accomplishes 100% threadsafe lazy initialization without any synchronization code:
public class MySingleton {
private static class MyWrapper {
static MySingleton INSTANCE = new MySingleton();
}
private MySingleton () {}
public static MySingleton getInstance() {
return MyWrapper.INSTANCE;
}
}
This will instantiate the singleton only when getInstance()
is called, and it's 100% threadsafe! It's a classic.
It works because the class loader has its own synchronization for handling static initialization of classes: You are guaranteed that all static initialization has completed before the class is used, and in this code the class is only used within the getInstance()
method, so that's when the class loaded loads the inner class.
As an aside, I look forward to the day when a @Singleton
annotation exists that handles such issues.
Edited:
A particular disbeliever has claimed that the wrapper class "does nothing". Here is proof that it does matter, albeit under special circumstances.
The basic difference is that with the wrapper class version, the singleton instance is created when the wrapper class is loaded, which when the first call the getInstance()
is made, but with the non-wrapped version - ie a simple static initialization - the instance is created when the main class is loaded.
If you have only simple invocation of the getInstance()
method, then there is almost no difference - the difference would be that all other sttic initialization would have completed before the instance is created when using the wrapped version, but this is easily dealt with by simply having the static instance variable listed last in the source.
However, if you are loading the class by name, the story is quite different. Invoking Class.forName(className)
on a class cuasing static initialization to occur, so if the singleton class to be used is a property of your server, with the simple version the static instance will be created when Class.forName()
is called, not when getInstance()
is called. I admit this is a little contrived, as you need to use reflection to get the instance, but nevertheless here's some complete working code that demonstrates my contention (each of the following classes is a top-level class):
public abstract class BaseSingleton {
private long createdAt = System.currentTimeMillis();
public String toString() {
return getClass().getSimpleName() + " was created " + (System.currentTimeMillis() - createdAt) + " ms ago";
}
}
public class EagerSingleton extends BaseSingleton {
private static final EagerSingleton INSTANCE = new EagerSingleton();
public static EagerSingleton getInstance() {
return INSTANCE;
}
}
public class LazySingleton extends BaseSingleton {
private static class Loader {
static final LazySingleton INSTANCE = new LazySingleton();
}
public static LazySingleton getInstance() {
return Loader.INSTANCE;
}
}
And the main:
public static void main(String[] args) throws Exception {
// Load the class - assume the name comes from a system property etc
Class<? extends BaseSingleton> lazyClazz = (Class<? extends BaseSingleton>) Class.forName("com.mypackage.LazySingleton");
Class<? extends BaseSingleton> eagerClazz = (Class<? extends BaseSingleton>) Class.forName("com.mypackage.EagerSingleton");
Thread.sleep(1000); // Introduce some delay between loading class and calling getInstance()
// Invoke the getInstace method on the class
BaseSingleton lazySingleton = (BaseSingleton) lazyClazz.getMethod("getInstance").invoke(lazyClazz);
BaseSingleton eagerSingleton = (BaseSingleton) eagerClazz.getMethod("getInstance").invoke(eagerClazz);
System.out.println(lazySingleton);
System.out.println(eagerSingleton);
}
Output:
LazySingleton was created 0 ms ago
EagerSingleton was created 1001 ms ago
As you can see, the non-wrapped, simple implementation is created when Class.forName()
is called, which may be before the static initialization is ready to be executed.
The task is non-trivial in theory, given that you want to make it truly thread safe.
A very nice paper on the matter is found @ IBM
Just getting the singleton does not need any sync, since it's just a read. So, just synchronize the setting of the Sync would do. Unless two treads try to create the singleton at start up at the same time, then you need to make sure check if the instance is set twice (one outside and one inside the sync) to avoid resetting the instance in a worst case scenario.
Then you might need to take into account how JIT (Just-in-time) compilers handle out-of-order writes. This code will be somewhat near the solution, although won't be 100% thread safe anyway:
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
Singleton inst = instance;
if (inst == null) {
synchronized(Singleton.class) {
instance = new Singleton();
}
}
}
}
return instance;
}
So, you should perhaps resort to something less lazy:
class Singleton {
private static Singleton instance = new Singleton();
private Singleton() { }
public static Singleton getInstance() {
return instance;
}
}
Or, a bit more bloated, but a more flexible way is to avoid using static singletons and use an injection framework such as Spring to manage instantiation of "singleton-ish" objects (and you can configure lazy initialization).