In the second form, your singleton is eagerly loaded and this is actually the preferred form (and the first one isn't thread-safe as you mentioned it yourself). Eager loading is not a bad thing for production code but there are contexts where you might want to lazy load your singletons, as discussed by the author of Guice, Bob Lee, in Lazy Loading Singletons that I'm quoting below:
First, why would you want to lazy load
a singleton? In production, you
typically want to eagerly load all
your singletons so you catch errors
early and take any performance hit up
front, but in tests and during
development, you only want to load
what you absolutely need so as not to
waste time.
Before Java 1.5, I lazy loaded
singletons using plain old
synchronization, simple but effective:
static Singleton instance;
public static synchronized Singleton getInstance() {
if (instance == null)
instance == new Singleton();
return instance;
}
Changes to the memory model in 1.5
enabled the infamous Double-Checked
Locking (DCL) idiom. To implement DCL,
you check a volatile
field in the
common path and only synchronize when
necessary:
static volatile Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null)
instance == new Singleton();
}
}
return instance;
}
But volatile
isn't that much faster
than synchronized
, synchronized
is
pretty fast nowadays, and DCL requires
more code, so even after 1.5 came out,
I continued using plain old
synchronization.
Imagine my surprise today when Jeremy
Manson pointed me to the
Initialization on Demand Holder
(IODH) idiom which requires very
little code and has zero
synchronization overhead. Zero, as in
even faster than volatile
. IODH
requires the same number of lines of
code as plain old synchronization, and
it's faster than DCL!
IODH utilizes lazy class
initialization. The JVM won't execute
a class's static initializer until you
actually touch something in the class.
This applies to static nested classes,
too. In the following example, the
JLS guarantees the JVM will not
initialize instance
until someone
calls getInstance()
:
static class SingletonHolder {
static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
[...]
Update: Credit where credit is due, Effective Java (copyright
2001) detailed this pattern under item
48. It goes on to point out that you still have to use synchronization or
DCL in non-static contexts.
I also switched singleton handling in
my framework from synchronization to
DCL and saw another 10% performance
boost (compared to before I started
using cglib's fast reflection). I only
used one thread in my micro-benchmark,
so the boost to concurrency could be
even greater given that I replaced a
heavily contended lock with a
relatively fine grained volatile field
access.
Note that Joshua Bloch now recommends (since Effective Java, 2nd ed) to implement singletons using a single-element enum
as pointed out by Jonik.