p1.
p1.

Reputation: 93

Singleton pattern implementation from Wikipedia

I am referring to the solution for the Singleton Pattern by Bill Pugh on Wikipedia:

public class Singleton
{

    // Private constructor prevents instantiation from other classes

    private Singleton() {}

     /**
    * SingletonHolder is loaded on the first execution of Singleton.getInstance() 
    * or the first access to SingletonHolder.INSTANCE, not before.
    */

    private static class SingletonHolder 
    { 

        private static final Singleton INSTANCE = new Singleton();
    }

   public static Singleton getInstance()
   {

       return SingletonHolder.INSTANCE;
   }

}

Here they have mentioned:

The inner 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).

However, isn't there a possibility that 2 threads would call getInstance() at the same time, which would lead to two instances of singleton being created? Isn't it safe to use synchronized here? If yes, where should it be used in the code?

Upvotes: 7

Views: 1780

Answers (7)

Pascal Thivent
Pascal Thivent

Reputation: 570285

This idiom is known as the Initialization on Demand Holder (IODH) idiom and is discussed in Item 48 of Effective Java as reminded by Bob Lee in his great post about Lazy Loading Singletons:

Item 48: Synchronize access to shared mutable data

(...)

The initialize-on-demand holder class idiom is appropriate for use when a static field is expensive to initialize and may not be needed, but will be used intensively if it is needed. This idiom is shown below:

// The initialize-on-demand holder class idiom
private static class FooHolder {
     static final Foo foo = new Foo();
}
public static Foo getFoo() { return FooHolder.foo; }

The idiom takes advantage of the guarantee that a class will not be initialized until it is used [JLS, 12.4.1]. When the getFoo method is invoked for the first time, it reads the field FooHolder.foo, causing the FooHolder class to get initialized. The beauty of this idiom is that the getFoo method is not synchronized and performs only a field access, so lazy initialization adds practically nothing to the cost of access. The only shortcoming of the idiom is that it does not work for instance fields, only for static fields.

However, in the Second Edition of Effective Java, Joshua explains how enums can be (ab)used for writing a serializable Singleton (this should be the preferred way with Java 5):

As of release 1.5, there is a third approach to implementing singletons. Simply make an enum type with one element:

// Enum singleton - the preferred approach
public enum Elvis {
     INSTANCE;
     public void leaveTheBuilding() { ... }
}

This approach is functionally equivalent to the public field approach, except that it is more concise, provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton.

Upvotes: 0

gpampara
gpampara

Reputation: 12049

There are two differences here that need to be noted. The first is the Singleton design pattern and the other is a singleton instance.

The Singleton design pattern is problematic due to the fact that the design pattern represents a singleton instance as is implemented using static state (which is a bad thing for a variety of reasons - especially with unit testing). The second is an instance for which there is only one instance, no matter what (like the JVM singleton implemented as an enum).

The enum version is definitely superior, when compared to the Singleton pattern.

If you don't want to implement all instances as enum instances, then you should think about using Dependency Injection (frameworks such as Google Guice) to manage the singleton instances for the application.

Upvotes: 0

Gregory Pakosz
Gregory Pakosz

Reputation: 70204

The JLS guarantees the JVM will not initialize instance until someone calls getInstance(); and that will be thread safe because it would happen during the class initialization of SingletonHolder.

However, since Java 5, the preferred approach involves Enum:

// Enum singleton - the preferred approach
public enum Elvis {
    INSTANCE;

    public void leaveTheBuilding() { ... }
}

Reference: Implementing the singleton pattern in Java

Upvotes: 5

stacker
stacker

Reputation: 68942

The Singleton is created when Singleton.getInstance() is called at this time the INSTANCE will be instantiated. Synchronization depends on a conrete implementation, since there are no values to modify (in this example) no synchronization is required.

Upvotes: 0

ZoogieZork
ZoogieZork

Reputation: 11279

See the "How it works", in the article "Initialization on demand holder idiom" linked from the same section.

In a nutshell, here's what happens when you call getInstance() the first time:

  1. The JVM sees a reference to SingletonHolder it has never seen referenced before.
  2. Execution is paused while it initializes SingletonHolder. This includes running any static initialization, which includes the singleton instance.
  3. Execution resumes. Any other threads calling getInstance() at the same time will see that SingletonHolder is already initialized. The Java spec guarantees that class initialization is thread-safe.

Upvotes: 12

alasdairg
alasdairg

Reputation: 2118

I think the idea is that Java guarantees that a class can only be initialized once, so implicitly only the first thread to access would cause this to happen

Upvotes: 0

danben
danben

Reputation: 83220

Here is the explanation from Wikipedia on this phenomenon (emphasis mine):

When the class Something is loaded by the JVM, the class goes through initialization. Since the class does not have any static variables to initialize, the initialization completes trivially. The static class definition LazyHolder within it is not initialized until the JVM determines that LazyHolder must be executed. The static class LazyHolder is only executed when the static method getInstance is invoked on the class Something, and the first time this happens the JVM will load and initialize the LazyHolder class. The initialization of the LazyHolder class results in static variable something being initialized by executing the (private) constructor for the outer class Something. Since the class initialization phase is guaranteed by the JLS to be serial, i.e., non-concurrent, no further synchronization is required in the static getInstance method during loading and initialization. And since the initialization phase writes the static variable something in a serial operation, all subsequent concurrent invocations of the getInstance will return the same correctly initialized something without incurring any additional synchronization overhead.

So in your example, Singleton is "LazyHolder" and SingletonHolder is "Something". Calling getInstance() twice will not cause a race condition due to the JLS guarantees.

Upvotes: 3

Related Questions