首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C# 單例模式:靜態 readonly 欄位實現線程安全與延遲初始化的深度解析

     編輯:程式設計疑難解答

題主代碼分析


public class Singleton {
    private Singleton() {}
    public static readonly Singleton instance = new Singleton(); // 靜態初始化器
}

結論

  • ✅ **線程安全**:CLR 保證靜態構造函數 (`.cctor`) 只執行一次,天然線程安全。
  • ❌ **非延遲初始化 (非懶漢模式)**:類被**首次訪問**時 (任何靜態成員、泛型實例化、反射獲取類型等) 即觸發初始化,而非首次調用 `Instance` 時。

三種單例實現對比

模式代碼要點線程安全延遲初始化性能
靜態 readonly (題主)`static readonly Instance = new T();`✅ CLR 保證❌ 類加載即初始化極高 (無鎖、無判斷)
雙重檢查鎖 (DCL)`if (instance==null) lock { if(instance==null) instance=new T(); }`✅ `volatile` + 鎖✅ 首次調用高 (首次鎖,後續無鎖)
嵌套類 (推薦)`class Holder { static readonly Instance = new T(); }`✅ CLR 保證✅ 訪問 Holder 時初始化極高 (無鎖、真正延遲)
Lazy<T> (現代首選)`static readonly Lazy lazy = new Lazy(() => new T());`✅ 內部實現✅ `lazy.Value` 時高、語義清晰

嵌套類實現 (真·懶漢+線程安全+零鎖)


public sealed class Singleton {
    private Singleton() {}
    public static Singleton Instance => Nested.instance;
    private class Nested {
        static Nested() {} // 顯式靜態構造函數觸發延遲
        internal static readonly Singleton instance = new Singleton();
    }
}

Lazy<T> 實現 (生產環境首選)


public sealed class Singleton {
    private Singleton() {}
    private static readonly Lazy _lazy = 
        new Lazy(() => new Singleton(), LazyThreadSafetyMode.ExecutionAndPublication);
    public static Singleton Instance => _lazy.Value;
}

題主面試追問回答要點

  1. `readonly` 只保證字段初始化後不可修改,**不保證延遲**。
  2. CLR 靜態構造函數 (`.cctor`) 執行時機:類首次被**主動使用** (訪問靜態字段/方法、實例化、反射等)。
  3. 若類還有其他靜態方法 (如 `Singleton.GetConfig()`),調用它也會觸發 `instance` 初始化,違背懶漢初衷。
  4. 嵌套類利用「嵌套類不隨外部類加載而加載」特性,完美實現延遲。`Lazy` 封裝了相同邏輯且 API 更清晰。

總結

題主代碼是**飽漢模式**變體 (靜態初始化),線程安全但非延遲。面試中若要求「多線程並發下的懶漢單例」,正確答案是 **嵌套類** 或 **Lazy<T>**,雙重檢查鎖次之 (需 `volatile`),單純 `static readonly` 不符合「懶漢」定義。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved