Thread-safe Singleton Design Implementation

Discussion in 'Java' started by yaru22, Jul 30, 2007.

  1. yaru22

    yaru22 Guest

    I was reading Wikipedia about Singleton Design pattern and it had some
    sample codes for the implementation.

    Under Java example implementation, there was "A thread-safe Java
    programming language lazy-loaded solution." But I don't understand why
    it is thread-safe & lazy-loaded solution. Could anyone explain it?

    This is the source code from the Wikipedia (http://en.wikipedia.org/
    wiki/Singleton_pattern) :
    public class Singleton
    {
    // Private constructor suppresses generation of a (public) default
    constructor
    private Singleton() {}

    private static class SingletonHolder
    {
    private final static Singleton INSTANCE = new Singleton();
    }

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

    Thank you.
    yaru22, Jul 30, 2007
    #1
    1. Advertising

  2. yaru22

    Eric Sosman Guest

    yaru22 wrote On 07/30/07 13:31,:
    > I was reading Wikipedia about Singleton Design pattern and it had some
    > sample codes for the implementation.
    >
    > Under Java example implementation, there was "A thread-safe Java
    > programming language lazy-loaded solution." But I don't understand why
    > it is thread-safe & lazy-loaded solution. Could anyone explain it?
    >
    > This is the source code from the Wikipedia (http://en.wikipedia.org/
    > wiki/Singleton_pattern) :
    > public class Singleton
    > {
    > // Private constructor suppresses generation of a (public) default
    > constructor
    > private Singleton() {}
    >
    > private static class SingletonHolder
    > {
    > private final static Singleton INSTANCE = new Singleton();
    > }
    >
    > public static Singleton getInstance()
    > {
    > return SingletonHolder.INSTANCE;
    > }
    > }


    Bloch explains this technique in "Effective Java."

    It is lazy-loaded because the SingletonHolder class
    is not loaded until it is needed, and it won't be needed
    until the first time someone calls getInstance.

    It is thread-safe because class loading is itself
    thread-safe. Only one thread will load SingletonHolder.
    If twenty-seven threads all call getInstance at the same
    time, SingletonHolder is still loaded and initialized only
    once, and all those threads see the same INSTANCE value.

    --
    Eric Sosman, Jul 30, 2007
    #2
    1. Advertising

  3. yaru22 wrote:
    > I was reading Wikipedia about Singleton Design pattern and it had some
    > sample codes for the implementation.
    >
    > Under Java example implementation, there was "A thread-safe Java
    > programming language lazy-loaded solution." But I don't understand why
    > it is thread-safe & lazy-loaded solution. Could anyone explain it?
    >
    > This is the source code from the Wikipedia (http://en.wikipedia.org/
    > wiki/Singleton_pattern) :
    > public class Singleton
    > {
    > // Private constructor suppresses generation of a (public) default
    > constructor
    > private Singleton() {}
    >
    > private static class SingletonHolder
    > {
    > private final static Singleton INSTANCE = new Singleton();
    > }
    >
    > public static Singleton getInstance()
    > {
    > return SingletonHolder.INSTANCE;
    > }
    > }


    I believe it is thread safe because class initialization is so and
    it is lazy loaded because SingletonHolder will first be initialized
    the first time Singleton.getInstance is called.

    It is one of the weird approaches people take to avoid using
    synchronized, which in most cases will work just fine.

    Arne
    =?ISO-8859-1?Q?Arne_Vajh=F8j?=, Jul 31, 2007
    #3
  4. Arne Vajhøj wrote:
    >
    >
    >
    > I believe it is thread safe because class initialization is so and
    > it is lazy loaded because SingletonHolder will first be initialized
    > the first time Singleton.getInstance is called.
    >
    > It is one of the weird approaches people take to avoid using
    > synchronized, which in most cases will work just fine.
    >
    > Arne


    One thing I don't like about lazy intitialization is the risk of
    intermittent StackOverflowExceptions for *complex* singleton classes....
    (which I've seen occur a number of times).

    Dave
    David Gourley, Jul 31, 2007
    #4
  5. yaru22

    Twisted Guest

    On Jul 31, 3:47 pm, David Gourley <>
    wrote:
    > One thing I don't like about lazy intitialization is the risk of
    > intermittent StackOverflowExceptions for *complex* singleton classes....
    > (which I've seen occur a number of times).


    I don't see why this would happen; the pattern doesn't produce a
    deeply nested call chain unless all classloading does on that
    implementation. In fact, the call chain is longer by as little as just
    1 stack frame:

    public class Singleton1 {
    private static Singleton1 instance = null;
    private Singleton1 () { ... }
    public static Singleton1 getInstance () {
    synchronized (Singleton1.class) {
    if (instance == null) instance = new Singleton1();
    return instance;
    }
    }
    }

    The ... is in Singleton1.Singleton1() called from
    Singleton1.getInstance()

    public class Singleton2 {
    private static class SingletonHolder {
    public static final Singleton2 instance = new Singleton2();
    }
    Singleton2 () { ... }
    public static Singleton2 getInstance () { return
    SingletonHolder.instance; }
    }

    The ... is in Singleton2.Singleton2() called from
    SingletonHolder.<static initializer> called from
    Singleton2.getInstance()

    There may be a few more between getInstance and the static initializer
    depending on how the class loading implementation you use works,
    likely including a loadClass(), but if it's pathologically many the
    class loading implementation you use ... well, to put it bluntly, it
    fucking blows. It is likely to cause problems at any point in the code
    that happens to trigger class loading, whether singleton-related or
    not.

    In particular, the complexity of the singleton class itself doesn't
    contribute anything to the nesting depth of calls unless the class
    loader is really brain-dead and does some sort of recursion instead of
    iteration on its members. So if the maximum is, say, 32768 nested
    method calls, you're no more likely to exceed that if Singleton2 has
    dozens of fields and methods than if Singleton2 has only one field and
    one method, assuming a sane classloader implementation.
    Twisted, Jul 31, 2007
    #5
  6. Twisted wrote:
    > On Jul 31, 3:47 pm, David Gourley <>
    > wrote:
    >
    >>One thing I don't like about lazy intitialization is the risk of
    >>intermittent StackOverflowExceptions for *complex* singleton classes....
    >>(which I've seen occur a number of times).

    >
    >
    > I don't see why this would happen; the pattern doesn't produce a
    > deeply nested call chain unless all classloading does on that
    > implementation. In fact, the call chain is longer by as little as just
    > 1 stack frame:


    But the class loader gets called from the current context in the current
    thread.

    See attached program (a bit evil because I knocked it up fairly quickly):

    class SingletonWrapper {
    static private SingletonWrapper mSw = new SingletonWrapper();

    private SingletonWrapper() {
    throw new RuntimeException("Give me a stack trace");
    }

    static public SingletonWrapper getInstance() {
    return mSw;
    }
    }
    class ClassLoaderTest {

    static public void main(String[] args) {
    int recurseDepth = Integer.parseInt(args[0]);
    recurse (0,recurseDepth);
    }

    static private void recurse (int currentDepth, int maxDepth) {
    try {
    if (currentDepth < maxDepth) {
    recurse(currentDepth+1,maxDepth);
    }
    else
    SingletonWrapper.getInstance();
    }
    catch (Exception e) {
    e.printStackTrace();
    }
    }
    }

    (you pass in a parameter saying how deep you want recursion to be before
    getInstance is called).

    java ClassLoaderTest 5:

    Exception in thread "main" java.lang.ExceptionInInitializerError
    at ClassLoaderTest.recurse(ClassLoaderTest.java:25)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.main(ClassLoaderTest.java:16)
    Caused by: java.lang.RuntimeException: Give me a stack trace
    at SingletonWrapper.<init>(ClassLoaderTest.java:5)
    at SingletonWrapper.<clinit>(ClassLoaderTest.java:2)
    ... 7 more

    java ClassLoaderTest 10:

    Exception in thread "main" java.lang.ExceptionInInitializerError
    at ClassLoaderTest.recurse(ClassLoaderTest.java:25)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.recurse(ClassLoaderTest.java:22)
    at ClassLoaderTest.main(ClassLoaderTest.java:16)
    Caused by: java.lang.RuntimeException: Give me a stack trace
    at SingletonWrapper.<init>(ClassLoaderTest.java:5)
    at SingletonWrapper.<clinit>(ClassLoaderTest.java:2)
    ... 12 more

    Now in my noddy example, there's not much on the stack frame. But I've
    seen cases where this triggered OutOfMemory...

    Dave
    David Gourley, Aug 1, 2007
    #6
  7. yaru22

    Twisted Guest

    On Aug 1, 4:57 pm, David Gourley <> wrote:
    > But the class loader gets called from the current context in the current
    > thread.


    I don't see this being unique to the situation of loading singletons.
    It seems likely to be just as much (or little) trouble any time
    classloading happens in mid-run.
    Twisted, Aug 2, 2007
    #7
  8. Twisted wrote:
    > On Aug 1, 4:57 pm, David Gourley <> wrote:
    >
    >>But the class loader gets called from the current context in the current
    >>thread.

    >
    >
    > I don't see this being unique to the situation of loading singletons.
    > It seems likely to be just as much (or little) trouble any time
    > classloading happens in mid-run.
    >


    Agreed it can happen other times.

    However (for whatever reason) I've seen it happen more frequently with
    singletons - and invariably happening for the first time in production
    (when events/user actions occur in a different order to during test)

    Dave
    David Gourley, Aug 2, 2007
    #8
  9. yaru22

    Twisted Guest

    On Aug 2, 3:51 pm, David Gourley <> wrote:
    > Agreed it can happen other times.
    >
    > However (for whatever reason) I've seen it happen more frequently with
    > singletons - and invariably happening for the first time in production
    > (when events/user actions occur in a different order to during test)


    How many call frames deep does Sun's classloader go ordinarily? Either
    it's excessive, or the application was teetering on the brink of a
    stack overflow anyway. Also, there's probably a -Xmx style VM
    commandline arg to increase the max stack depth for such deployments.
    Twisted, Aug 2, 2007
    #9
  10. Twisted wrote:

    > How many call frames deep does Sun's classloader go ordinarily? Either
    > it's excessive, or the application was teetering on the brink of a
    > stack overflow anyway. Also, there's probably a -Xmx style VM
    > commandline arg to increase the max stack depth for such deployments.
    >


    The classloader isn't necessarily the problem... eventually the
    singleton constructor gets called - the depth of the call stack under
    *its* constructor could be the problem. Yes - increasing the stack size
    fixes the problem: I'd just prefer not to find this out on a live
    system with high availability requirements.

    Since running into these problems I've steered clear of lazy
    initialisation of complex singletons (I prefer to explicitly initialise
    them up front and have deterministic behaviour).

    Dave
    David Gourley, Aug 2, 2007
    #10
  11. yaru22

    Twisted Guest

    On Aug 2, 5:50 pm, David Gourley <> wrote:
    > The classloader isn't necessarily the problem... eventually the
    > singleton constructor gets called - the depth of the call stack under
    > *its* constructor could be the problem.


    In this case, the classloading-based trick isn't the problem at all;
    the design of the constructor is such that any lazy instantiation
    whatsoever carries roughly the same risk, however its thread-safety is
    achieved (or even if it isn't!). If there's no way to reduce deep call
    chaining (e.g. by turning recursion into iteration) in that
    constructor, you should use eager initialization in your main() method
    or thereabouts.

    Another trick of course is to actually spawn a new thread to do the
    initialization:

    public MySingleton () {
    final Object lock = new Object();
    new Thread(new Runnable() {
    public void run () {
    initialize(lock);
    }
    }).start();
    synchronized (lock) {
    lock.wait();
    }
    }

    public void initialize (Object lock) {
    ...
    synchronized (lock) {
    lock.notify();
    }
    }

    The new thread has its own call stack and the initialization code has
    only the one parent stack frame, the run() method of the anonymous
    inner class. This is equivalent to the initialize() code being in the
    constructor and the constructor being directly invoked from main() via
    "MySingleton.instance = new MySingleton();" or whatever.

    The lock object is used here simply to make the constructor block
    until construction is actually complete; the execution is supposed to
    be effectively serial, as the thread is not actually for
    parallelization but to get an empty new stack with plenty of room to
    play around in more or less for free.

    The thread creation is relatively expensive but only happens the once
    given that the constructor is called only once (perhaps lazily).
    Twisted, Aug 3, 2007
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?V2lsbGlhbSBTdWxsaXZhbg==?=

    Thread safe singleton to access the cache?

    =?Utf-8?B?V2lsbGlhbSBTdWxsaXZhbg==?=, Oct 6, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    781
    Bruce Barker
    Oct 6, 2005
  2. Anand
    Replies:
    11
    Views:
    9,834
    Jacob
    Feb 10, 2006
  3. =?Utf-8?B?RGlmZmlkZW50?=

    Singleton and thread-safe

    =?Utf-8?B?RGlmZmlkZW50?=, Dec 9, 2006, in forum: ASP .Net
    Replies:
    2
    Views:
    299
    =?Utf-8?B?TWFuaXNoIEJhZm5h?=
    Dec 9, 2006
  4. Gabriel Rossetti
    Replies:
    0
    Views:
    1,293
    Gabriel Rossetti
    Aug 29, 2008
  5. John Nagle
    Replies:
    5
    Views:
    447
    John Nagle
    Mar 12, 2012
Loading...

Share This Page