34

I'm reading wiki about the singleton pattern and I'm not sure if I understand this: https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom part of it correctly.

So to make it simple: Why is Bill Pugh's solution better than the example above?

Is it because a static class is not load by the VM before it's actually used or something like this, so we don't create the object before we turn to the getInstance() method? Also is that method thread safe only to the extent of initializing the object?

Rob Fox
  • 5,355
  • 7
  • 37
  • 63

6 Answers6

32

I think Mr Pugh's version is held in high regard because it only performs the instantiation of the singleton when getInstance() is called i.e. not when the class (the class holding the getInstance method) is loaded. If your singleton construction does something costly then this may be an advantage for you. If you're like the majority of the world whose singletons are just to avoid static methods (and you haven't moved onto dependency injection frameworks), then I would not lose any sleep over it.

As the article states, Mr Pugh's method is lazier than the static instance variable - but in reality if the Singleton class gets loaded you're going to be calling the getInstance method anyhow. So as a computer science exercise it's useful, but in the real world its benefits are debatable.

p.s. I don't care much for Mr Bloch's example here as to use an enum would be to say My Singleton IS-A enum, which doesn't sound right to me (especially from someone who, rightly, says never implement an interface just to get the constants)

Hearen
  • 7,420
  • 4
  • 53
  • 63
planetjones
  • 12,469
  • 5
  • 50
  • 51
  • But if my class holds no methods other than the singleton then It won't be instantiated before getInstance() is called anyway? – Rob Fox May 24 '11 at 12:01
  • the static class in Mr Pugh's example will only get loaded when getInstance is called, as that's the first time it is referenced. Your public class holding the getInstance method will probably only have the getInstance method - so as I say above from a computer science view it's interesting, but practically it's very little difference to the "traditional simple way" – planetjones May 24 '11 at 12:04
  • I've come around to the enum way of thinking because there are a statically-knowable number of instances of the class. It's like the class example of Suits where there are exactly four; here we have an enum with exactly one member, `INSTANCE`. Though I can appreciate the viewpoint that this is confusing. (However the "weirdness" of this single instance being statically defined is really just accentuating the weaknesses of the singleton pattern. How would you feel for an enum about a "dual-ton", `enum DatabaseConnection { LIVE, TEST }`?) – Andrzej Doyle May 24 '11 at 12:04
  • @Andrzej Doyle I think there is mileage in your point. I guess I see enums being used when there is some meaning in the enum values i.e. that makes functional sense and where you only want a single representation of that value in your system. I have seen classes such as CustomerLogic or AccountLogic implemented as a Singleton (just to avoid static methods) and in that case I couldn't see an enum being the logical fit, even though technically it fits the job. – planetjones May 24 '11 at 12:17
  • @planetjones actually the public class holding the getInstance() method will often have at least one instance method (e.g. java.awt.Toolkit) -- the important point is that getInstance() is called _first_. – Andy Oct 24 '13 at 00:50
  • More pertinently, if your singleton construction does something *leaky*, such as opening input/output streams, database connections, etc., Bill Pugh's method gives you a cleaner way to handle exceptions. See also http://stackoverflow.com/a/1371559/318912 (I know this because I have lost sleep over it, not worrying about it, but resolving real-world issues caused by lack of thread safety in singletons.) – Alex Nauda Sep 16 '14 at 14:11
  • To better understand the Bill Pugh's Singleton, it's extremely important to understand, besides the Thread-safe arguments, the difference between loading a class and initializing it. Please, check the answer at https://stackoverflow.com/a/45828372/2457251 and re-read some explanations here. It will make them clearer. – Almir Campos Aug 22 '17 at 23:51
  • static singleton class' instantiation happens as any data member or method of this class is accessed. – Arun Raaj Mar 12 '19 at 14:17
31

The JLS guarantees that a class is only loaded when it's used for the first time (making the singleton initialization lazy), and that the class loading is thread-safe (making the getInstance() method thread-safe as well)

As for why thread-safe

Because the first time getInstance() is called, the JVM will load the holder class. If another thread calls getInstance() concurrently, the JVM won't load the holder class a second time: it will wait for the first thread to have completed the class loading, and at the end of the loading and initialization of the holder class, both thread will see the holder class properly initialized and thus containing the unique singleton instance.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Hi, I actually don't understand, how it is thread-safe. Can you please explain? – arnabkaycee May 30 '15 at 12:57
  • 15
    Because the first time getInstance() is called, the JVM will hold the holder class. If another thread calls getInstance() concurrently, the JVM won't load the holder class a second time: it will wait for the first thread to have completed the class loading, and at the end of the loading and initialization of the holder class, both thread will see the holder class properly initialized and thus containing the unique singleton instance. – JB Nizet May 30 '15 at 13:09
8

Is it because a static class is not load by the VM before it's actually used

Not just a static class, any class. Classes aren't loaded until they are referenced. See the JLS - 12.4.1 When Initialization Occurs

or something like this, so we don't create the object before we turn to the getInstance() method?

Exactly.

Also is that method thread safe only to the extent of initializing the object?

Handing out a reference is thread-safe, so this method is always thread-safe, not just at creation time

Sarang Sharma
  • 18
  • 1
  • 5
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
2

The key part of the explanation is the following:

The nested class is referenced no earlier (and therefore loaded no earlier by the class loader) than the moment that getInstance() is called. Thus, this solution is thread-safe without requiring special language constructs (i.e. volatile or synchronized).

Bill Pogh's solution provides laziness.

khachik
  • 28,112
  • 9
  • 59
  • 94
1

Is it because a static class is not load by the VM before it's actually used or something like this, so we don't create the object before we turn to the getInstance() method?

Correct.

Also is that method thread safe only to the extent of initializing the object?

It ensures that only one instance is created and no client receives anything but a reference to that fully initialized instances.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
0

Static inner class will contain the Singleton instance. It will create the Singleton instance when the static inner class is loaded into the memory. It doesn't require synchronization.

public class Singleton {

private Singleton (){}

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

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

}