I happened upon an article recently discussing the double checked locking pattern in Java and its pitfalls and now I'm wondering if a variant of that pattern that I've been using for years now is subject to any issues.
I've looked at many posts and articles on the subject and understand the potential issues with getting a reference to a partially constructed object, and as far as I can tell, I don't think my implementation is subject to these issues. Are there any issues with the following pattern?
And, if not, why don't people use it? I've never seen it recommended in any of the discussion I've seen around this issue.
public class Test {
private static Test instance;
private static boolean initialized = false;
public static Test getInstance() {
if (!initialized) {
synchronized (Test.class) {
if (!initialized) {
instance = new Test();
initialized = true;
}
}
}
return instance;
}
}
That would work if
initializedwasvolatile. Just as withsynchronizedthe interesting effects ofvolatileare not really so much to do with the reference as what we can say about other data. Setting up of theinstancefield and theTestobject is forced to happen-before the write toinitialized. When using the cached value through the short circuit, theinitializeread happens-before reading ofinstanceand objects reached through the reference. There is no significant difference in having a separateinitializedflag (other than it causes even more complexity in the code).(The rules for
finalfields in constructors for unsafe publication are a little different.)However, you should rarely see the bug in this case. The chances of getting into trouble when using for the first time is minimal, and it is a non-repeated race.
The code is over-complicated. You could just write it as: