2

Usually I use the first implementation. Couple of days ago I found another. Can anyone explain me the difference between these 2 implementations ? The 2nd implementation is thread safe? What is the advantage of using inner class in the 2nd example?

//--1st Impl
public class Singleton{

      private static Singleton _INSTANCE;

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

//--2nd Impl
public class Singleton {
      private Singleton() {}

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

      public static Singleton getInstance() {
            return SingletonHolder._INSTANCE;
      }
}
sura2k
  • 7,365
  • 13
  • 61
  • 80

4 Answers4

7

The first implementation uses what is called a "double checked lock". This is a Very Bad Thing. It looks thread-safe, but in fact it is not.

The second implementation is, indeed, thread-safe.

The explanation for why the first implementation is broken is fairly involved, so I'd recommend you get a copy of Brian Goetz's Java Concurrency in Practice for a detailed explanation. The short version is that the compiler is allowed to assign the _INSTANCE variable before the constructor has completed, which can cause a second thread to see a partially-constructed object.

Cameron Skinner
  • 51,692
  • 2
  • 65
  • 86
3

The first implementation is only and only thread-safe if the _INSTANCE is made volatile. The second one is thread safe because the _INSTANCE is only initialized once the SingletonHolder is loaded by the class loader.

So when the inner class is accessed for the time (much later than the whole program was loaded), the class loader loads the inner-class and initializes the variable. So for any later access, the object is readily available Hence the method getInstance() is thread-safe.

The beauty of the second implementation, is you dont have to worry about synchronization or count as class loader does it for you

Jatin
  • 31,116
  • 15
  • 98
  • 163
1

#1 is designed to ensure lazy initialization. But, in the given case, #2 ensures lazy initialization too. _INSTANCE is created only when Singleton.class is loaded, and Singleton.class is loaded on first invocation of getSingleton(). There is no other method in the class. No double checked locking needed. And of course in #1 _INSTANCE should be volatile.

Note: I do not agree that double checked locking is bad. When implemented correctly it may be very useful.

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
0

The first code snippet is an example of the double-checked locking idiom, which used to be quite popular but is now known to be unsafe and should never be used.

The second snippet uses the combination of the semantics of class loading and of the final keyword, as defined by the Java language specification, to ensure lazy initialization and thread safety, so it is much better.

Daniel Pryden
  • 59,486
  • 16
  • 97
  • 135
  • `final` doesn't ensure either lazy initialization or thread safety. The second implementation is taking advantage of the way class loading works. – Cameron Skinner Dec 01 '12 at 04:33
  • @CameronSkinner: yes, but the definite assignment semantics of `final` ensure that only one instance is ever assigned, and that the write is safely published to other threads. – Daniel Pryden Dec 01 '12 at 04:36
  • Fair enough. `final` still has nothing to do with laziness, however. – Cameron Skinner Dec 01 '12 at 04:37