When is a singleton not a singleton?

Avoid multiple singleton instances by keeping these tips in mind

1 2 Page 2
Page 2 of 2

Two singletons will be created if the constructor runs and simultaneously another thread calls the method. Thread-safe code is particularly important in singletons, since that Design Pattern is meant to give the user a single point of access that hides the complexities of the implementation, including multithreading issues.

Multiple instances can be created even if you add a synchronized(this) block to the constructor call, as in Listing 4:

Listing 4

// Also an error, synchronization does not prevent
// two calls of constructor.
public static MySingleton getInstance() {
    if (_instance==null) {
      synchronized (MySingleton.class) {
         _instance = new MySingleton();
      }
    }
    return _instance;
}

In the correct solution, seen in Listing 5, make getInstance() a synchronized method:

Listing 5

// correct solution
public static synchronized MySingleton getInstance() {
// . . . continue as in Listing 3

Double-checked locking is another common solution but, unfortunately, it does not work (see Listing 6).

Listing 6

// Double-checked locking -- don't use
public static MySingleton getInstance() {
    if (_instance==null) {
      synchronized (MySingleton.class) {
        if (_instance==null) {
           _instance = new MySingleton();
        }
      }
    }
}

In this situation, we intend to avoid the expense of grabbing the lock of the singleton class every time the method is called. The lock is grabbed only if the singleton instance does not exist, and then the existence of the instance is checked again in case another thread passed the first check an instant before the current thread.

Unfortunately, double-checked locking causes problems. To wit, compiler optimizations can make the assignment of the new singleton object before all its fields are initialized. (See "Double-checked locking is broken" in Resources.) The only practical solution is to synchronize the getInstance() method (as in Listing 2).

Multiple singletons arising when someone has subclassed your singleton

The Singleton design pattern is meant to give you control over access to the singleton class. While I have mostly discussed the control of instantiation, other code can access your class another way: by subclassing it.

The uniqueness of the class cannot be imposed as a compile-time constraint on the subclass unless you use a private constructor. If you want to allow subclassing, for example, you might make the constructor protected. A subclass could then expose a public constructor, allowing anyone to make instances. Since an instance of a subclass is an instance of your superclass, you could find multiple instances of the singleton.

Multiple singletons created by a factory specially asked to create multiple objects

One of the strengths of the Singleton design pattern, as opposed to static methods, is that if you change your mind and want more than one, the singleton class can be easily altered.

For example, most servlets run as singletons in their servlet engines. Since that can cause threading problems, in one alternative (not recommended, but available) the servlet can implement SingleThreadModel. In that case, the servlet engine may, if necessary, create more than one servlet instance. If you are used to the more common singleton servlets, you may forget that some servlets can occur in multiple instances.

Copies of a singleton object that has undergone serialization and deserialization

If you have a serialized object and deserialize it twice in different ObjectOutputStreams, or with calls ObjectOutputStream.reset() between deserializations, you get two distinct objects, not two references to the same object.

Likewise, when you serialize an object with an ObjectOutputStream, the closure of its graph of references serializes with it. If the ObjectOutputStream closes and a new one opens, or if reset() is called on the ObjectOutputStream, the graph of references breaks and a new one is started. So if you serialize one singleton twice, the two serialized objects take on separate identities.

The object serialization of the java.io package is not the only way to serialize Java objects. New mechanisms of object serialization with XML have been developed, including those associated with SOAP, WDDX, and KOALA, among others. With all those mechanisms, a reconstituted object loses its referential identity, and you have to consider carefully whether your singleton is still a singleton.

Multiple singletons caused by problems in a factory

In some implementations of creational design patterns in the factory family, the factory is a singleton structured to create an instance of another class. That second class might not have any singleton-like protection against multiple instantiation, on the grounds that the factory will ensure that it constructs only one instance.

If you accidentally have more than one factory object for one of the reasons above, you will still have two of the created objects, even if each factory object is built correctly.

Conclusion

Singletons are a useful way to control access to a class, making sure that only one instance can exist. In some none-too-uncommon circumstances, however, multiple instances can occur, even in a class coded as a singleton. By being aware of the possibility, you can be sure that your singleton really is a singleton.

In this article, I've presented some ways that the multiple singleton might emerge. If you've discovered any others, I'd be interested in hearing about them.

Acknowledgement

My thanks to Alexander Radzin for valuable comments on this article.

Learn more about this topic

1 2 Page 2
Page 2 of 2