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

C# 設計模式實作:單例模式完整範例與執行緒安全探討

     編輯:關於C語言

模式意圖

確保一個類別只有一個實例,並提供全域存取點。本範例展示最基礎的「懶漢式」實作,並說明其在多執行緒環境下的問題與改進方向。

基本實作(非執行緒安全)

using System;

class SingletonPage
{
    private static SingletonPage _instance;

    // 私有建構子,防止外部 new
    protected SingletonPage()
    {
        Console.WriteLine("唯一實例被建立!");
    }

    // 公開靜態方法取得實例
    public static SingletonPage GetInstance()
    {
        if (_instance == null)
            _instance = new SingletonPage();
        return _instance;
    }
}

// 測試
class TestApp
{
    public static void Main()
    {
        Console.WriteLine("'create' pagea:");
        var a = SingletonPage.GetInstance();

        Console.WriteLine("'create' pageb:");
        var b = SingletonPage.GetInstance();

        Console.WriteLine("'create' pagec:");
        var c = SingletonPage.GetInstance();

        Console.WriteLine("'create' paged:");
        var d = SingletonPage.GetInstance();

        Console.WriteLine($"所有變數指向同一實例: {ReferenceEquals(a, b) && ReferenceEquals(b, c) && ReferenceEquals(c, d)}");
    }
}

執行結果

'create' pagea:
唯一實例被建立!
'create' pageb:
'create' pagec:
'create' paged:
所有變數指向同一實例: True

多執行緒安全問題

上述 if (_instance == null) 檢查與 new SingletonPage() 非原子操作,多執行緒同時進入可能建立多個實例。

改進版:雙重檢查鎖定


class SingletonPage
{
    private static SingletonPage _instance;
    private static readonly object _lock = new object();

    private SingletonPage() { Console.WriteLine("Instance created"); }

    public static SingletonPage GetInstance()
    {
        if (_instance == null) // 第一次檢查,避免每次進鎖
        {
            lock (_instance) // 鎖定
            {
                if (_instance == null) // 第二次檢查
                    _instance = new SingletonPage();
            }
        }
        return _instance;
    }
}

現代 C# 建議做法:Lazy<T>


using System;

class SingletonPage
{
    private SingletonPage() { Console.WriteLine("Instance created"); }

    private static readonly Lazy _lazy = 
        new Lazy(() => new SingletonPage(), true); // true = 執行緒安全

    public static SingletonPage Instance => _lazy.Value;
}
  • Lazy<T> 內建雙重檢查鎖定,程式碼簡潔且效能佳。
  • true 參數啟用發布模式下的執行緒安全。

何時使用單例

  • 記錄器、配置管理器、連線池、快取等「全域唯一」資源。
  • 避免濫用:單例會增加耦合、難以單元測試、隱藏依賴關係。優先考慮依賴注入(DI 容器管理生命週期)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved