Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
January 25, 2002
n "Singletons Rule," "Effective Object-Oriented Design," and "n Class Instances," I addressed questions regarding the Singleton design pattern. As many readers have since pointed out, you must take special
care to ensure that singletons are thread safe. With that in mind, in this Java Q&A I explore singletons and thread safety.
Let's begin by looking at a nonthread-safe singleton:
public class Singleton {
private static Singleton instance;
public static Singleton getInstance() {
if( instance == null ) {
instance = new Singleton();
}
return instance;
}
private Singleton() {}
public static void main( String [] args ) {
Singleton instance = Singleton.getInstance();
// ... manipulate instance
}
}
Unfortunately, in the example above, a thread may at any time pre-empt the call to getInstance(). For example, a thread may pre-empt a running thread at instance = new Singleton. If that were to happen, multiple Singleton instances might instantiate, thus defeating the purpose of a singleton.
To make a singleton thread safe, you have two choices. The first simply synchronizes the getInstance() method:
public class Singleton {
private static Singleton instance;
public synchronized static Singleton getInstance() {
if( instance == null ) {
instance = new Singleton();
}
return instance;
}
private Singleton() {}
public static void main( String [] args ) {
Singleton instance = Singleton.getInstance();
// ...
}
}
Synchronizing the method guarantees that a call to the method cannot be interrupted.
The second approach to thread safety declares a constant Singleton attribute on the Singleton class itself:
public class Singleton {
public final static Singleton instance = new Singleton();
private Singleton() {}
public static void main( String [] args ) {
Singleton instance = Singleton.instance;
// ...
}
}
instance will initialize when the class loades. Both solutions guarantee only one Singleton will exist.
In "n Class Instances," I presented an alternate approach to singletons that allows multiple instances of an object but caps the number of instances at some number. In that article, the following method retrieved the instance:
public static AlternateSingleton instance()
{
return instances.next();
}
As you can see, instance() is not thread safe because it retrieves the instance from a nonthread-safe data structure. If a thread pre-empts instances.next() at the wrong time, the same instance may be returned multiple times in a row. Fortunately, fixing the problem is as easy
as synchronizing the method:
public synchronized static AlternateSingleton instance()
{
return instances.next();
}
Not everyone believes singletons represent the best design choice, while others believe that singletons have their place when used carefully.
When thinking about using a singleton, it is a good idea to check out the arguments for and against the pattern.
As one drawback, the Singleton as I implemented above makes inheritance impossible (the constructor is private). So you can lose some object-oriented programming
(OOP) benefits when you decide to make a class a singleton. However, other approaches to implementing the Singleton pattern
allow you to use inheritance or to treat the singleton polymorphically. For example, you can combine an interface, multiple
implementations, and a factory to boost your singletons' flexibility. Let's examine each piece of this alternate approach.