DEV Community

Sota
Sota

Posted on

Singleton Pattern

What is Singleton Pattern?

The singleton pattern is a creational pattern that ensures a class has only one instance, and provides a global point of access to it.

When to use it?

Use Singleton pattern when you want to ensure only one instance of a class exists in application.

Problem

Let's try to implement our Singleton pattern.

public class Singleton {

    private static Singleton instance;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Singleton class holds static variable instance, this is our one and only instance of Singleton class.
  • Constructor is declared as private so that nobody can't instantiate Singleton class except for Singleton class itself.
  • getInstance() returns instance of Singleton class. In this code, instance gets created when it is needed, this is called lazy instantiation.

Can you spot the problem? Think what happens when we're in multithreading environment.

The problem occurs more than one thread call getInstance() at the same time. Let's see how it occurs when we have two threads...

  1. Thread1 checks if instance is null or not, we haven't called getInstance() before, thus instance == null is true.
  2. Thread2 also calls getInstance() and check if instance is null. Because Thread1 just entered inside if block and didn't create object, instance is still null.
  3. Thread1 instantiates Singleton class with new keyword.
  4. Thread2 also instantiates Singleton class.

We now have two Singleton objects, which is not desired.

Such a situation is called race condition, where multiple threads attempt to access to shared resources at the same time but its outcome is indeterministic.

Solution 1

public class Singleton {

    private static Singleton instance;

    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
Enter fullscreen mode Exit fullscreen mode

Solution is just adding synchronized keyword to getInstance(). synchronized keyword can ensure only one thread can enter the method at the time and other threads wait their turn.

This works fine but synchronization is expensive. synchronization is only needed when getInstance() is called for the first time since once we get instance of Singleton, getInstance() won't enter if block and just return an object that already has been created. After the first time through, synchronization is totally unneeded overhead.

Solution 2

We can implement eager instantiation Singleton if our application always creates and uses an instance of Singleton.

public class Singleton {

    // Create an instance when Singleton class is loaded by JVM
    private static Singleton instance = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        // instance has already been created
        return instance;
    }
}
Enter fullscreen mode Exit fullscreen mode

Solution 3

if performance of getInstance() is an issue (like we pointed out in Solution 1), we can implement double-checked locking Singleton.
As name indicates, this implementation does null-check for our instance twice.

  1. First check: if instance is null, it enters the block.
  2. Synchronization: lock on Singleton class object (Class object is a runtime representation of the class), this ensures only one thread at a time executes the synchronized block. The synchronized block represents critical section.
  3. Second check: this check can't occur at a time because of synchronization.
public class Singleton {

    private volatile static Singleton instance;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (instance == null) { // First check
            synchronized (Singleton.class) { // Synchronization
                if (instance == null) { // Second check
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
Enter fullscreen mode Exit fullscreen mode

Solution 4

Singleton sounds simple but it has many things we have to consider such as synchronization, class loading, reflection and serialization/deserialization issues. Is there any better implementation that resolves these issues? Yes, enum provides simple implementation and resolves all the issues above.

public enum Singleton {
    INSTANCE;
}
Enter fullscreen mode Exit fullscreen mode

We don't need to write our own private constructor because JVM will instantiate our INSTANCE automatically.

Structure

Image description

Pitfalls

  • Singleton violates the single responsibility principle as it does two jobs, ensuring only one instance exists & providing a global access point to that instance.

You can check all the design pattern implementations here.
GitHub Repository


P.S.
I'm new to write tech blog, if you have advice to improve my writing, or have any confusing point, please leave a comment!
Thank you for reading :)

Top comments (0)