DEV Community

Abdullah Al Mahmud
Abdullah Al Mahmud

Posted on • Edited on

🔎Exploring Design Patterns: Thread Safe Singleton Pattern in C#

Singleton (Thread Safe)

private static readonly Lazy<DbConnectionThreadSafe> _instance = null!; 
Enter fullscreen mode Exit fullscreen mode

Using Lazy<T> Because

  • Thread safe by default
  • Provides lazy initialization
static DbConnectionThreadSafe() { _instance = new Lazy<DbConnectionThreadSafe>( () => new DbConnectionThreadSafe(_connectionString), LazyThreadSafetyMode.ExecutionAndPublication ); } 
Enter fullscreen mode Exit fullscreen mode

Let's break down this static constructor and the Lazy initialization:

static DbConnection() // This is a static constructor { _lazyInstance = new Lazy<DbConnection>( () => new DbConnection(_connectionString), // Lambda expression LazyThreadSafetyMode.ExecutionAndPublication // Thread safety mode ); } 
Enter fullscreen mode Exit fullscreen mode

Let's examine each part:

  1. Static Constructor (static DbConnection())

    • A static constructor is called automatically before any static members are referenced
    • It runs only once per app domain
    • It's thread-safe by default (CLR guarantees this)
    • Used to initialize static fields
  2. Lazy

    • Lazy<T> is a class that provides lazy initialization
    • The actual object isn't created until it's first accessed
    • When you access Lazy<T>.Value for the first time, it creates the instance
  3. Lambda Expression (() => new DbConnection(_connectionString))

    • This is a factory function that creates the DbConnection instance
    • It's only executed when the Lazy.Value is first accessed
    • The => syntax defines a lambda expression (anonymous function)
  4. LazyThreadSafetyMode.ExecutionAndPublication

    • This enum value specifies how the Lazy instance handles thread safety
    • Three possible modes:
// No thread safety LazyThreadSafetyMode.None // Locks initialization LazyThreadSafetyMode.ExecutionAndPublication // Multiple threads can attempt initialization LazyThreadSafetyMode.PublicationOnly 
Enter fullscreen mode Exit fullscreen mode

The execution flow:

  1. When the class is first referenced, the static constructor runs
  2. The _lazyInstance is created, but the DbConnection instance is not yet created
  3. When Instance is first accessed:
    • The lambda expression runs
    • Creates new DbConnection with the connection string
    • Stores it in the Lazy instance
  4. Subsequent accesses to Instance return the same stored instance

Top comments (0)