Creational Pattern: Singleton

Erçin Dedeoğlu
4 min readNov 30, 2022

--

This article discusses how the Singleton pattern enforces only a single instance of a class ever to get produced and exist through the lifetime of an application.

What is it?

A singleton is a design pattern used to create the only class instance. Singleton pattern is typically used when there are several examples where only a single instance of a class should exist and the constraint be enforced. For example, caches, thread pools, and registries should only have one instance.

Make the constructor private to ensure that only one class object is created. That way, only the class members can access the private constructor and no one else.

In the real world, the Singleton pattern ensures that only a single class instance exists and offers a global point of access to it.

Class Diagram

The class diagram contains only one entity.

Singleton

Example

Let’s say we want to model the American President’s official aircraft called Airforce One in our software. Singleton class is the best-suited representation for an entity with only one instance.

Here is the code for our singleton class:

Multithreading and Singleton

This code works as long as the application is single-threaded. However, if multiple threads access this class, there is a possibility that various objects will be created.

For example:

  • Thread A calls the method getInstanceand finds the onlyInstanceto be null; however, before it can create an instance, it is context switched out.
  • Now thread B comes along and calls getInstance, which returns the AirforceOneobject.
  • If thread A is scheduled again, the mischief begins. The thread is already past the if-null condition check and will proceed to create a new AirforceOneobject and assign it to onlyInstance. Now there are two different AirforceOneobjects out in the wild, one with thread A and one with thread B.

There are two simple ways to fix this race condition.

  • By adding synchronized to the getInstance() method, you can achieve thread safety.
  • Another option is to initialize the instance statically, guaranteeing it is thread-safe.

The problem with the above approaches is that synchronization is expensive and static initialization creates the object even if it’s not used in a particular application run. So if the object creation is expensive, then static initialization can cost us performance.

Double-Checked Locking

There are two significant problems with the approaches described above: synchronization is expensive and static initialization creates the object even if it’s not used in a particular application run. If the object creation is expensive, then static initialization can cost us performance.

The above solution marks the singleton instance volatile. However, this implementation of the JVM’s volatile methodology will not work correctly for double-checked locking, and you’ll need another approach to create your singletons.

The double-checked locking idiom is now considered an antipattern, and its utility has primarily passed away as JVM startup times have sped up.

Other Examples

The Java API provides us with the following singletons:

java.lang.Runtime

java.awt.Desktop

Caveats

You can subclass a singleton class by protecting the constructor instead of private. However, there are better choices than this under all circumstances. In these situations, developers can create a registry of singletons for all the subclasses. The getInstance method can take in a parameter or use an environment variable to return the desired singleton object. The registry maintains a mapping of string names to singleton objects.

Other articles in the Creational Pattern series

My other publications: https://ercindedeoglu.github.io/

--

--

Erçin Dedeoğlu
Erçin Dedeoğlu

Written by Erçin Dedeoğlu

I am passionate about solving problems and developing products to make people’s lives easier.

No responses yet