首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

C# 多執行緒安全 Singleton 雙重檢查鎖定模板 (含 volatile 與 Lazy<T> 現代寫法)

     編輯:ASP.NET 基礎

經典雙重檢查鎖定 (Double-Check Locking)

適用於 .NET Framework 早期版本,需搭配 volatile 防止指令重排序導致執行緒讀到未完全初始化的實例。

public sealed class Singleton where T : class, new()
{
    private static volatile T _instance = null;
    private static readonly object _lock = new object();

    private Singleton() { }

    public static T Instance
    {
        get
        {
            if (_instance == null) // 第一次檢查 (無鎖,效能佳)
            {
                lock (_lock) // 同步鎖
                {
                    if (_instance == null) // 第二次檢查 (防止多執行緒同時通過第一次檢查)
                        _instance = new T();
                }
            }
            return _instance;
        }
    }

    // 手動重置實例 (如配置熱更新)
    public static void RefreshInstance()
    {
        lock (_lock)
        {
            _instance = new T();
        }
    }
}

關鍵點解析

關鍵字作用
volatile確保 `_instance` 讀寫不被 CPU/編譯器重排序,保證其他執行緒看到完全初始化後的物件。
readonly object _lock專用鎖物件,避免 `lock(this)` 或 `lock(typeof(T))` 造成死鎖風險。
sealed + 私有建構子防止繼承與外部實例化,強制單例。
雙重檢查第一次無鎖判斷提升高併發效能;第二次在鎖內確保只建立一次。

現代最佳實踐:Lazy<T> (推薦 .NET 4.0+)

System.Lazy 內建執行緒安全、延遲初始化、效能優化,程式碼極度精簡:

public sealed class Singleton where T : class, new()
{
    private static readonly Lazy _lazy = new Lazy(() => new T(), LazyThreadSafetyMode.ExecutionAndPublication);

    private Singleton() { }

    public static T Instance => _lazy.Value;

    public static void RefreshInstance()
    {
        // Lazy 無法直接重置,需重新建立 Lazy 實例 (罕見需求)
        // 若必須支援重置,建議維持經典寫法或自行實作可重置的 Lazy 包裝器
    }
}
  • LazyThreadSafetyMode.ExecutionAndPublication:確保多執行緒下僅執行一次初始化,且發佈可見性正確 (預設值)。
  • 無需手寫 volatile、lock,框架層級保證正確性。

進階:支援依賴注入 (DI) 的單例

現代 ASP.NET Core 應用不建議手寫 Singleton,直接註冊服務生命週期:

// Program.cs / Startup.cs
services.AddSingleton(); // 容器管理單例生命週期

優點:支援建構子注入、單元測試易 Mock、生命週期由容器統一管理。

總結建議

  1. 新專案 (.NET Core / .NET 5+):優先使用 DI 容器 AddSingleton。
  2. 需手寫 Singleton 的舊專案/庫:採用 Lazy 簡潔安全。
  3. 極少數需手動控制初始化時機/重置:使用經典 volatile + 雙重檢查鎖定。
  4. 切記:Singleton 非銀彈,濫用會導致強耦合、難測試、隱藏依賴,請審慎評估。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved