1

I am trying to find my own way of Java Singleton implementation. The code is as follows:

public class Singleton{
   private volatile static Singleton _instance = null;
   private Singleton(){}
   public static Singleton getInstance(){
      if (_instance == null)
         Object obj = new Object();
         synchronized(obj){
            if (_instance == null)
               _instance = new Singleton();
         }
      return _instance;
}

Does this code work? If not work, how to fix it?

Adam Arold
  • 29,285
  • 22
  • 112
  • 207
Zachary
  • 1,633
  • 2
  • 22
  • 34
  • You are using a method local lock, which totally invalidates your synchronization (effectively, there is none). – Perception May 10 '13 at 13:40
  • You should have a look at `Jon Skeet's` singleton implementation. Pretty much covers your issue. – christopher May 10 '13 at 13:41
  • Here is another question, showing Skeet's method mentioned above [http://stackoverflow.com/questions/2912281/thread-safety-in-singleton] – mconlin May 10 '13 at 13:44
  • @Perception Could you explain in more details? – Zachary May 10 '13 at 13:44
  • what Perception is saying is that, if synchronized always locks on a new object, there's no way other threads will be contending for the same lock. So it doesn't limit concurrent access at all. – Nathan Hughes May 10 '13 at 13:52
  • [What is an efficient way to implement a singleton pattern in Java?](http://stackoverflow.com/questions/70689/) – fredoverflow May 10 '13 at 16:56

5 Answers5

3

No - your code doesn't work, because the lock object is a local variable and therefore different for every thread.

You are attempting to implement the lazy initialization pattern - where the instance is created when first used.

But there is a simple trick that allows you to code a thread-safe implementation that doesn't require synchronization! It is known as the Initialization-on-demand holder idiom, and it looks like this:

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

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

    private Singleton() {
    }

    // rest of class omitted
}

This code initializes the instance on the first calling of getInstance(), and importantly dosen't need synchronization because of the contract of the class loader:

  • the class loader loads classes when they are first accessed (in this case Holder's only access is within the getInstance()` method)
  • when a class is loaded, and before anyone can use it, all static initializers are guaranteed to be executed (that's when Holder's static block fires)
  • the class loader has its own synchronization built right in that make the above two points guaranteed to be threadsafe

It's a neat little trick that I use whenever I need lazy initialization. You also get the bonus of a final instance, even thought it's created lazily. Also note how clean and simple the code is.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
2

Ticky and really simple implementation of not-lazy singleton:

public enum TickySingleton {

    INSTANCE;

    public void doSomething() { ... }
    public Object returnSomething() { ... }
}

}

Not everybody will like this. ;)

rebeliagamer
  • 1,257
  • 17
  • 33
  • I just found out someone wrote about that implementation here: http://stackoverflow.com/questions/2912281/thread-safety-in-singleton – rebeliagamer May 10 '13 at 13:51
  • 1
    This 'enum singleton pattern' is also recommended by Josh Bloch in the book 'Effective Java' – eiden May 10 '13 at 14:55
1

it would be better if your synchronization object is final static. Otherwise each possible concurrent thread will create its own sync object and lock different objects. And they will not wait for each other.

public class Singleton{

   private final static Object obj = new Object();
   private volatile static Singleton _instance = null;

   private Singleton(){}

   public static Singleton getInstance(){
     if (_instance == null)
        synchronized(obj){
           if (_instance == null)
              _instance = new Singleton();
         }
      }
      return _instance;
   }
Mehmet Ataş
  • 11,081
  • 6
  • 51
  • 78
  • Yes. I find my problem. The object can not be in the method. Otherwise, each time the method is called, a new different object is created. Does not work. – Zachary May 10 '13 at 13:48
1

When you write:

Object obj = new Object();
synchronized(obj){}

The JVM can prove that no two threads can acquire that lock (because it is a local variable) and can therefore completely remove the synchronization.

A few comments about singletons:

Community
  • 1
  • 1
assylias
  • 321,522
  • 82
  • 660
  • 783
0

No, it's not correct, you should synchronize on Singleton.class

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

it's a known double-checked locking pattern, see http://www.ibm.com/developerworks/java/library/j-dcl/index.html for details

Note that since there's only one method in this class the following serves the same purpose without any double-checked tricks and it's lazy too

class Singleton {
       private static Singleton _instance = new Singleton();
       private Singleton(){}
       public static Singleton getInstance(){
          return _instance;
    }
}
assylias
  • 321,522
  • 82
  • 660
  • 783
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • fyi double-checked locking is considered an anti-pattern – Bohemian May 10 '13 at 14:15
  • and your second example is not lazy. the instance will be created when the class is first required to be loaded, not necessarily used – Bohemian May 10 '13 at 14:28
  • @Bohemian but it is lazy, it's similar to "lazy initialization holder class idiom" from Effective Java – Evgeniy Dorofeev May 10 '13 at 14:54
  • It is *not* lazy. As I said before, the instance will be created when the class is *loaded*, not when `getInstance()` is first called. It may be loaded due to a dependency long before it is needed, often at server start up, which is why the holder idiom is used - with it the class may be loaded *without* creating the singleton instance. – Bohemian May 10 '13 at 15:00
  • @EvgeniyDorofeev Actually, the singleton class might have other members, i.e. other public static variable which is the real usage of singleton – Zachary May 10 '13 at 15:00
  • @bohemian Why you said double-checked locking is considered an anti-pattern? – Zachary May 10 '13 at 15:02
  • @bohemian the Singleton class here, there is only one way of access it, by calling the getInstance method. So only when calling this method, the class is loaded. I cannot find other ways of loading Singleton class. – Zachary May 10 '13 at 15:09
  • @assylias Actually, you *do* need the `volatile` keyword, otherwise you get the "double checked locking anti-pattern" problem, due to the java memory model not requiring that writes "happens before" reads for non-volatile fields. See [this article](http://reentrantthoughts.blogspot.com.au/2010/03/on-why-double-check-locking-in-anti.html) for more – Bohemian May 10 '13 at 15:11
  • @Zack See [this famous article](http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html) for the reason it's called an anti-pattern. In later version of java, the volatile keyword and a change to the java memory model specification resurrected this pattern back to the living (see [this article](http://reentrantthoughts.blogspot.com.au/2010/03/on-why-double-check-locking-in-anti.html), but it's inferior to the holder idiom (see my answer) – Bohemian May 10 '13 at 15:18
  • 1
    @Zack Regarding class being loaded *before* calling `getInstance()`, *any* reference to the class, even the `Singleton.class` object, perhaps due to a logging initialization parameter or an `instanceof Singleton` test or whatever, will cause the class to be loaded, which can be *long* before the `Singleton.getInstance()` method is called. – Bohemian May 10 '13 at 15:19
  • @Bohemian You only need volatile in his first example, not in his second example. – assylias May 10 '13 at 15:30
  • @assylias Right. Must have skimmed (again) :) – Bohemian May 10 '13 at 15:31