Singletons and lazy loading

by Dejan Bosanac

Probably the first design pattern that every software developer learns is Singleton and lazy loading of Singleton classes.

The usual example, goes something like this:

public class Singleton {

static Singleton instance;

public static synchronized Singleton getInstance() {
if (instance == null)
instance = new Singleton();
return instance;
}

}


The problem with this solution is that synchronized method getInstance() is called every time, while synchronization is actually needed only for the first call of the method (which introduces performance overhead in your application). There were attempts to tackle this problem by using Double-checked locking pattern, which although great in theory didn't work in practice.

Today, thanks to Bob Lee, I found out that there is a solution to this problem that is both simple and fast: Initialization on Demand Holder (IODH) idiom. The appropriate example follows:

public class Singleton {

static class SingletonHolder {
static Singleton instance = new Singleton();
}

public static Singleton getInstance() {
return SingletonHolder.instance;
}

}


Basicaly, Java Language Specification (JLS) guarantees that instance would not be initialized until someone calls getInstance() method (more information could be found in articles that I've linked to before). Elegant and fast, just as it should be.

27 Comments


2007-01-26 08:01:32
Why not use the simple and classic solution :



public class Singleton {
private static Singleton instance = new Singleton();


private Singleton() {/*effective initialisation here*/ }


public static Singleton getInstance() {
return instance;
}
}

David Dossot
2007-01-26 08:06:50
Because you are not lazy initializing with this code.


Re IODH, JLS also garantees that only one thread will perform the loading, which is why the "synchronized" keyword is waived.


D.

asdf
2007-01-26 08:55:08
My understanding is the following:
1. Static members get initialized when the classloader loads the class
2. Classloaders load classes the first time they get accessed


Since the first access of a singleton will almost always be getInstance, wouldn't lazy initialization save us nothing?


In the rare circumstance, where you have other static methods on a singleton, lazy initialization may have benefits, but this defeats the purpose of the singleton.


I suppose there are a few other rare circumstances (e.g. reflection).


Please correct me if I am wrong.

Jack K
2007-01-26 09:03:03
But that is not lazy initalisation !
Marcus
2007-01-26 09:17:28
I can't really say where I'd use a lazily initialized Singleton. If I really want a Singleton, I'll likely want it initialized early, and then have it around. If I care about making sure something is lazily initialized, I probably don't want it as a Singleton anyway.


However, it is a good implementation...

Christoph
2007-01-26 09:36:09
If your singleton instance needs e.g. expensive database access for initialization, lazy initialization is usually a good way to do it.
Andrew McCormick
2007-01-26 09:44:22
I agree with Marcus. I'll be pleasantly surprised when I interview someone and ask the best way to implement a singleton, and they say "You don't". There are very very few types for whom one-and-only-one is a fundamental attribute of the type. Mostly its "I'd like to run in an environment where there's only one of these", which is more of a container issue than a class issue.
Stefan
2007-01-26 10:20:12
If you can avoid singletons, do it. Using singletons is initially quite fast, but it can demote testability.
Bob Lee
2007-01-26 10:24:09
asdf, you're right--if the there's nothing else in the class, you don't need the nested class.
Adam
2007-01-26 11:58:02
The problem with this solution is its a black box to the uninitiated. This is the kind of 'cleverness' that screams for some comments in the code explaining why you're doing this. You shouldn't assume that other programmers have read the Wikipedia entry or memorized section 12.4 of the JLS.
KDGregory
2007-01-26 13:05:24
+1 for ASDF: as long as you don't actually execute any methods or construct any instances of a Singleton class, static initialization is lazy loading. If you don't believe it, compile the following two classes:


public class Main {
public static void main(String[] argv) throws Exception {
SingletonClass ref = null;
System.out.println("main sleeping: " + System.nanoTime());
Thread.sleep(500L);
ref = SingletonClass.getInstance();
}
}
----
public class SingletonClass {

static {
System.out.println("SingletonClass is loaded: " + System.nanoTime());
}

static SingletonClass instance = new SingletonClass();

public static SingletonClass getInstance() {
return instance;
}

private SingletonClass() {
System.out.println("singleton being constructed: " + System.nanoTime());
}
}
---
In the posting, the author is just adding another layer of indirection. Maybe useful if Singleton provides additional static methods or public static variables, but not if your only access is through getInstance().


One big problem with using static initializers is what happens when one throws an exception. Especially if the static initializer is using a class that also has a static initializer. Trying to debug this situation can be a nightmare, especially in an environment where multiple threads might hit the failing initializer in a non-deterministic order.

matthew
2007-01-26 13:33:30
Why not this? (I can't get the formatting quite right.)


public class Singleton {
private static Singleton instance;


private Singleton() {}


public static synchronized Singleton getInstance() {
return (instance != null) ? instance : (instance = new Singleton())
}
}

Tom
2007-01-27 11:23:16
Matthew --


The point is that synchronizing the getInstance() method makes it slower -- and 99% of the time it doesn't need to be synchronized.


And I don't think you can "return instance = new Singleton()" which is what your ternary operator is doing when instance!=null.

peter
2007-01-28 08:08:31
and what about this?


public class Singleton {


private static Singleton instance;


private static synchronized initSingleton(){
instance = new Singleton()
}

public static Singleton getInstance() {
if (instance == null)
instance == initSingleton();
return instance;
}


}

gio
2007-01-28 11:18:13
I used to know the following pattern as suggested by core j2ee patterns, anyway yours is clever.


public class Singleton {


private Singleton instance = null;


static {
instance = new Singleton();
}


private Singleton() {
// ANY INIT CODE HERE
}


public Singleton getInstance() {
return this.instance;
}


}

Hans
2007-01-28 12:10:37
Josh Bloch described the SingletonHolder many years ago in Effective Java, which I suggest you read (or read again.) It should be required reading for anyone writing in Java.


Singletons are highly overused, as is lazy loading. Singltons are abused to solve design problems, and create hassles for proper testing. They're nothing but global variables, which are evil. Yes there are a few (very few) uses for them, but not to the extent we commonly see. Lazy loading only makes sense when there's something expensive that needs to be put off until later, or something expensive that may never be needed. Like most performance related issues, expensive is usually overstated and not measured.


I'm skeptical of the real need to use SingletonHolder.

Eugene Kaganovich
2007-01-28 20:38:45
From what I understand, Double-checked Locking is fixed as of Java 5, and will work on previous versions as well as long as the program runs on a single-processor machine.


So, I think it's perfectly fine to use it in most cases.


That said, this solution is pretty nice.


2007-01-29 08:09:08
erm... this is absolutely pointless...


You could just have your singleton variable instantiated and omit the if is null condtion from the method. take out the synchronized and robert is then your father's brother.

Matt
2007-01-29 11:51:30
This is not valid:
public static Singleton getInstance() {
if (instance == null)
instance == initSingleton();
return instance;
}


The reason being that there is a potential for multiple object construction here. Take the following sequencing:


1. thread 1 enters getInstance, sees that instance is null
2. execution switches to thread 2
3. thread 2 enters getInstance, sees that instance is null.


Once this happens, both threads think the instance is null, so the initInstance method will be called in each thread.


If you want the approach above, you can change your initInstance method as follows:


private static synchronized void initSingleton(){
if (instance == null) {
instance = new Singleton();
}
}


At least in that case, if you call initSingleton twice, it will not construct the instance a second time.
(Don't quote me on this, but off the top of my head, it will work)

Michael Hallenberger
2007-01-30 01:29:52
compiler error on line 4!
instance == new Singleton();


this looks like better:
instance = new Singleton();

Dejan Bosanac
2007-01-30 01:44:33
Fixed ... Thanks
James Watson
2007-01-30 07:43:14
This is idiom does not strictly guarantee lazy-loading. You can call this and it will load the inner class without calling getInstance, even if the nested class is private:


Class.forName("Singleton$SingletonHolder");


The JLS section that is mentioned here states this explicitly. I'm not saying this is likely, I just think it's wrong to tell people that things are 'guaranteed' when they are not. It would be fairly trivial to write a neat little 'helper' to parse through the classpath and pre-load all the classes in it. That would break this idiom and if your depended on lazy-loading for correctness, it could be a problem.

Tom
2007-02-01 07:58:17
I thought this problem was resolved long ago with this even simpler code (no need for nested classes)


public class Singleton {


static Singleton instance= new Singleton ();


private Singleton (){
}
public static synchronized Singleton getInstance() {
return instance;
}
}

Pat Toner
2007-02-01 12:44:57
Cool, thanks.
Krishna Srinivasan
2007-02-12 18:21:09
Good stuf.
Struts 2.0
Sam
2007-02-14 07:27:12
Is it just me, or does not accessing a class require the JVM to obtain a lock on the class to ensure that the same class is not loaded more than once?


http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#44630
It seems to me that synchronization is still taking place each time, you just don't have to do it explicitly yourself

AAA
2007-02-26 08:40:16
maybe also this in the 'appropriate example'
private Singleton() {
}


?:D