The Singleton Pattern

Daniel Boyce
4 min readDec 17, 2023

Introduction

The Singleton Pattern ( SP ) is another creational design pattern. It ensures that a class has only one instance and it also provides a global point of access to it.

Composition

What is a singleton composed of?

A private constructor which prevents direct instantiation of the class from outside.

A static instance variable that holds the single instance of the class, usually private and static.

A static method ( usually called something like getInstance() ) which provides a way to access the single instance. Depending on the implementation, this might create the instance if it doesn’t already exist, or just return the instance.

Thread safety

A concept we will need to have an understanding of moving forward is thread safety. Thread safety refers to the ability of a program to function correctly and maintain its integrity when multiple threads are executing concurrently.

With the singleton in mind, securing thread safety is crucial because multiple threads might attempt to access and potentially create the singleton instance simultaneously.

If not handled properly this could lead to potential issues like multiple threads simultaneously initializing more than one instance of the singleton which could lead to inconsistent behavior. We will explore an approach that considers thread safety and addresses the concern.

Example

It’s important to remember that a class implementing the SP is more than a singleton, it is a general purpose class with it’s own set of data and methods. This example being an exception to display the properties that make a singleton a singleton.

Below we have our first example of a singleton, known as an Eager singleton. As you can see we have all of the components outlined above in our example.

A private constructor, a static instance and a static method.

public class Singleton {
private static Singleton instance = new Singleton();

private Singleton() {}

public static Singleton getInstance() {
return instance;
}
}

This type of singleton ensures that the instance is created at the time of class loading. This guarantees thread safety but should only be used if the singleton will always be needed.

If there is a possibility the singleton may not always be needed this may not be the most efficient path to take and we have another approach for this scenario.

Below we have our second example and this is known as a Lazy singleton.

public class Singleton {
private static Singleton instance;

private Singleton() {}

public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

You can see compared to our eager singleton, this one moves our initialization into the getInstance() so it will only be initialized when it is called for not when the classes are loaded. This can be considered more efficient but now we are at risk of those safety threading issues mentioned earlier.

I have one final example to reveal. This example is still considered a lazy singleton but it introduces a technique that will remove any safety threading concerns. This technique is known as double-checked locking.

public class Singleton {
private static volatile Singleton instance;

private Singleton() {}

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

Here we use the keyword ‘volatile’ for the singleton instance and this ensures that multiple threads handle the instance variable correctly when it is being initialized.

The getInstance() method now has two if statements, the first checks to see if the instance == null without synchronization. If it is null then it proceeds to acquire a lock. ( This means that only one thread can enter this block of code at a time. )

We use the outer if statement to prevent any unnecessary uses of the ‘synchronized’ keyword as it can introduce expensive overhead in our program.

Benefits

Some of the benefits of using the SP include :

Global Access which provides a single point of access to an instance, making it accessible from anywhere in the application.

Resource management that ensures efficient use of resources by having only one instance for resource intensive objects.

Lazy initialization ( specifically for the lazy implementation ) which allows for on-demand creation of the instance that can potentially improve performance by delaying instantiation until it’s necessary.

Tradeoffs

Some of the trade offs from using the SP include :

Global state might lead to tight coupling and hidden dependencies.

Concurrency and thread safety. As mentioned above, implementing a singleton in a multi-threaded environment requires consideration to ensure thread safety particularly in lazy implementations.

Sources

Ana Peterlić, https://www.baeldung.com/java-patterns-singleton-cons

Java Design Patterns & Solid Design Principles, Udemy by Coffee Powered Crew

https://www.udemy.com/course/design-patterns-in-java-concepts-hands-on-projects/

Head First Design Patterns by Freeman and Robson

https://www.amazon.co.uk/Head-First-Design-Patterns-Freeman/dp/0596007124/ref=sr_1_2?crid=3PIU1ST6993RY&keywords=head+first+design+patterns&qid=1701246040&sprefix=head+first+design+patterns%2Caps%2C54&sr=8-2

--

--

Daniel Boyce

Interested in all things tech. I'm using this platform mainly as a place to store things that I think I will want to revise in the future