Design Patterns
3. Public Static Property (Instance Property)

To provide global access to the Singleton instance, a public static property (Instance property) is often used. This property ensures that clients can obtain the Singleton instance without directly accessing the private instance variable.


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

Lazy Initialization

The Instance property uses lazy initialization to create the Singleton instance when it's accessed for the first time (instance == null). This approach defers the creation of the Singleton instance until it's actually needed, saving resources and improving performance.

4. Thread Safety Considerations

Simple Lazy Initialization (Non-Thread-Safe)

The basic implementation of lazy initialization shown above is not thread-safe. In a multi-threaded environment, multiple threads could simultaneously execute the Instance property getter and create multiple instances of Singleton.

Thread-Safe Singleton using Locking

To ensure thread safety, you can use locking to synchronize access to the Instance property. This prevents multiple threads from creating multiple instances concurrently.


public static Singleton Instance
{
    get
    {
        lock (syncRoot)
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
        }
        return instance;
    }
}
private static readonly object syncRoot = new object();

Thread-Safe Singleton using Lazy

C# also provides a built-in Lazy class that simplifies lazy initialization and ensures thread safety without explicit locking.


private static readonly Lazy lazyInstance =
    new Lazy(() => new Singleton());

public static Singleton Instance => lazyInstance.Value;