I have come across some code, where the developer is constantly checking if the singleton is null twice with a nested if - like in the code below:
private st
This does not make any sence unless the singleton is a property which creates the instance in the getter, but even then this would not make sense then the rest of the code would be unreachable.
It is a failed attempt to achieve Double Checked Locking Idiom. The first null
check is to see if the instance is already created and if it is not null
then just return the instance already created.
But the condition check is a check-then-act situation and is not thread safe, so there is a possibility that two or more threads will see the value as null
and create two instances of singleton and thats doubleton or maybe ManyTon.
So we use synchronized
so that only one thread enters that block and only a single instance is created.
I think you're referring to Double Checked Locking. This pattern allows you to avoid synchronization when it is not needed.
You code should be
private static volatile ProcessManager singleton = null;
public static ProcessManager getInstance() throws Exception {
if (singleton == null) {
synchronized (MyClass.class) {
if (singleton == null) {
singleton = new ProcessManager();
}
}
}
return singleton;
}
So you see we only sync when we have checked that the singleton is not null, we then recheck just in case someone has already begun to build it. Note that for this to work, the singleton must be volatile
. Here is an article that explains the subtle issue that arises, if you forget the volatile
.
In your case, where the method is synchronized, you are right. There is no point in checking twice.
The technique is called double checking.
The code you pasted, however, is incorrect. You are right, it makes no sense to double check for null value in that way. I would say that correct implementation of double check is following:
private static volatile ProcessManager instance = null;
public static ProcessManager getInstance() {
if (instance == null) {
synchronized(ProcessManager.class) {
if (instance == null) {
instance = new ProcessManager();
}
}
}
return instance;
}
Notice that second null check is synchronized on ProcessManager.class object. It is necessary because getInstance() method is a static one.
Your code doesn't demonstrate the case properly. This stems from the double-checked idiom, where it does make sense:
// Double-check idiom for lazy initialization of instance fields.
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) { // First check (no locking)
synchronized(this) {
result = field;
if (result == null) // Second check (with locking)
field = result = computeFieldValue();
}
}
return result;
}
Read about it over here.
Be careful to note that this idiom is a good choice only for instance fields. In your question you have a static
field, for which case a much simpler idiom is the primary choice: the lazy initialion holder class idiom:
// Lazy initialization holder class idiom for static fields
private static class FieldHolder {
static final FieldType field = computeFieldValue();
}
static FieldType getField() { return FieldHolder.field; }