Skip to the content.

Singleton

© Ioannis Kostaras


Name Singleton
Scope Object
Purpose Creational
Intent Ensure that a class has only one instance and provide a global point of access to it.
Also Known As  
Motivation It is necessary for some classes to have only one instance; e.g., to hold system-wide state information or manage a resource (e.g. a database)
Applicability when there must be exactly one instance of a class, and it must be accessible from a well-known point of access
Structure
Participants A Singleton class defines a static member function that returns a pointer to the sole instance of the class. This Instance() function creates the instance if it does not already exist
Collaborations Clients access the sole instance solely through this function

Implementation

Java

Let’s start with the simplest implementation. How can we guarantee a single instance?

public final class Singleton {
    public static final Singleton INSTANCE = new Singleton();

    // private empty constructor
    private Singleton() {
       // initialize any state here
    }
    // ...	
}

public class Client {
    public static void main(String[] args) {
        // Constructor is private -- cannot use new
        Singleton s1 = Singleton.INSTANCE;
        Singleton s2 = Singleton.INSTANCE;

        if ( s1 == s2 )
            System.out.println( "Same instance" );
    }
}

A static class is one of the approaches that makes a class “Singleton”, since static means shared by all objects of the class. There should be no other way to construct an object apart from the one provided by the class. To achieve that:

This implementation is also thread safe, since static final guarantees that the object will be created.

A similar way is to use a factory method to provide the single point of access:

// Singleton using a factory method
public final class Singleton {
    private static final Singleton INSTANCE = new Singleton();

    // private empty constructor
    private Singleton() {
        // initialize any state here
    }
    
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

Lazy initialisation is useful for expensive objects (by lazy initialisation we mean initialise the object only when needed, i.e. when the Singleton class is being called for the first time):

// Singleton with lazy initialization
public final class Singleton {
    private static Singleton singleton = null;

    // private constructor
    private Singleton() {
        // initialize any state here
    }
    
    public static Singleton getInstance() {
     if (singleton == null) 
            singleton = new Singleton();	
        return singleton;
    }
}

public class Client {
    public static void main(String[] args) {
        // Constructor is private -- cannot use new
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();

        if ( s1 == s2 )
            System.out.println( "Same instance" );
    }
}

However, the above implementation is not thread-safe. To make it thread-safe:

// Thread-safe singleton with lazy initialization
public final class Singleton {
    private volatile static Singleton singleton = null;
    private static final Object classLock = Singleton.class; 

    // private constructor
    private Singleton() {
        // initialize any state here
    }
    public static Singleton getInstance() {
        if (singleton == null) 
            synchronized (classLock) {
                if (singleton == null) 
                    singleton = new Singleton();	
                return singleton;
            }
    }
}

Double-checked locking in Java is considered correct and safe under the Java Memory Model (JMM) only if the shared field (the singleton instance) is declared volatile and all object construction is complete before publishing the reference.

Without volatile, the object construction and the assignment to the reference can be reordered, leading to another thread seeing a partially-initialized object. Declaring the singleton reference as volatile prevents this reordering and ensures visibility of the fully constructed object to all threads.

Note: Double check locking doesn’t work in JVM 1.4 or earlier (in case you ‘re still working with such old versions).

All initialization must be done before assigning the reference to instance, to avoid leaking a partially-constructed object.

As a refresher, when you are using a synchronized marker, you have two choices on its granularity: “method locks” or “block locks”. If you put the synchronized on a method, you are locking on this object implicitly.

An effective lazy initialisation can be provided by using a Holder class:

// Singleton that uses a Holder class
public final class Singleton {
    private static class SingletonHolder {
        static final Singleton INSTANCE = new Singleton();
        private SingletonHolder() {}
    } 

    // private constructor
    private Singleton() {
        // initialize any state here
    }
    
    public static Singleton getInstance() { 	
        return SingletonHolder.INSTANCE;
    }
}

The class loader guarantees that the class is correctly initialised.

If you need a Singleton that can be serialized:

public final class Singleton implements Serializable {
    public static final Singleton INSTANCE = new Singleton();

    // private empty constructor
    private Singleton() {
        // initialize any state here
    }	
    // readResolve method to preserve singleton property
    private Object readResolve() {
    // Return the instance and let the garbage collector
    // take care of the rest.
        return INSTANCE;
    }
}

If you don’t implement readResolve(), then on the other side, a new Singleton object will be created.

Since Java 5.0 you can use enums:

// Singleton using enum
public enum Singleton {
    INSTANCE;
}

But if the constructor(s) are private, how can we pass arguments to a Singleton?

C#

// Singleton pattern -- Lazy initialization  
using System;  
// "Singleton"  
class Singleton {   
    // Fields   
    private static Singleton instance;    
    // Constructor   
    protected Singleton() {}
    // Methods   
    public static Singleton Instance()   {     
        // Uses "Lazy initialization"     
        if ( instance == null ) {       
            instance = new Singleton();     
            return instance;   
        } 
    }
}

Client code test:

/// <summary>
/// Client test
/// </summary>
public class Client
{
  public static void Main()
  {
    // Constructor is protected -- cannot use new
    Singleton s1 = Singleton.Instance();
    Singleton s2 = Singleton.Instance();

    if ( s1 == s2 )
      Console.WriteLine( "The same instance" );
  }
}

Below is a thread-safe Singleton implementation:

// Singleton pattern – Thread safe - Lazy initialization
using System;

// "Singleton"
class Singleton
{
   // Fields
   private static volatile Singleton? instance = null;
   // Lock synchronization object
   private static object syncLock = new object();

   // Constructor
   private Singleton() {}
   // Methods
   public static Singleton Instance()
   {
	  // Support multithreaded applications through
	  // "Double checked locking" pattern which (once
 	  // the instance exists) avoids
	  // locking every time the method is invoked
        if (instance == null)
        {
            lock (syncLock)
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
            }
        }
        return instance;
   }
}

C++

// Singleton.h
class Singleton {

public:
    static Singleton* Instance();
private:
    static Singleton* pInstance;
    Singleton();
};

// Singleton.cpp
#include "Singleton.h"

Singleton* Singleton::Instance() 
{
    if (pInstance == nullptr)
    {
        pInstance = new Singleton;
    }
    return pInstance;
}
Singleton* Singleton::pInstance = nullptr;

// 

Rust

Known Uses

Java

C++

C#

Rust

## Known Uses ### Java

C#

C++

// Singleton.h
class Singleton {
  public:
    static Singleton* Instance();
    // Prevent copy
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;    
  private:
    static Singleton* pInstance;
    Singleton() {};
};

// Singleton.cpp
#include "Singleton.h"
Singleton* Singleton::Instance() 
{
    if (pInstance == nullptr)
    {
        pInstance = new Singleton;
    }
    return pInstance;
}
// Static member initialization
Singleton* Singleton::pInstance = nullptr;

// Client.cpp
#include "Singleton.h"
#include <iostream>

using namespace std;

int main()
{
    Singleton* singleton1 = Singleton::Instance();
    Singleton* singleton2 = Singleton::Instance();

    if (singleton1 == singleton2) 
        cout << "Same instances.";
    else 
        cout << "Different instances.";
}

Rust

## Consequences ### Pros

Comparison of Singleton to a class of static methods

Why use Singleton when one could just create a final class and declare all its methods as static?

public final class StaticClass {
  public static String getMethodA() {}
  public static int getMethodB() {}
  // ...
}

A global variable makes an object accessible, but has drawbacks

Bibliography and further reading