確保類別在應用程式生命週期內僅有一個實例,並提供全域存取點(非全域變數)。適用於:計數器、設定管理器、連線池、日誌記錄器等。
public sealed class Singleton {
private static readonly Singleton instance = new Singleton();
private Singleton() { } // 私有建構子防止外部 new
public static Singleton Instance { get { return instance; } }
}
public sealed class Singleton {
private static Singleton instance;
private Singleton() { }
public static Singleton Instance {
get {
if (instance == null)
instance = new Singleton(); // 非執行緒安全!
return instance;
}
}
}
null 檢查 → 建立兩個實例public class Counter {
private static Counter uniqueInstance;
private int count = 0;
private Counter() { Thread.Sleep(100); } // 模擬初始化延遲
public static Counter Instance {
get {
if (uniqueInstance == null)
uniqueInstance = new Counter();
return uniqueInstance;
}
}
public void Increment() { count++; }
public int Count { get { return count; } }
}
四個執行緒各遞增 4 次,預期 16。若無同步,可能出現計數歸零(重複初始化)。
[MethodImpl(MethodImplOptions.Synchronized)]
public static Counter Instance {
get {
if (uniqueInstance == null)
uniqueInstance = new Counter();
return uniqueInstance;
}
}
鎖定整個方法(相當於 lock(this) 或 lock(typeof(Counter)))。
private static readonly object syncLock = new object();
public static Counter Instance {
get {
lock (syncLock) {
if (uniqueInstance == null)
uniqueInstance = new Counter();
return uniqueInstance;
}
}
}
private static Mutex mutex = new Mutex();
public static Counter Instance {
get {
mutex.WaitOne();
try {
if (uniqueInstance == null)
uniqueInstance = new Counter();
return uniqueInstance;
} finally {
mutex.ReleaseMutex();
}
}
}
AbandonedMutexExceptionpublic static Counter Instance {
get {
if (uniqueInstance == null) { // 第一次檢查:無鎖,效能佳
lock (syncLock) {
if (uniqueInstance == null) // 第二次檢查:持鎖
uniqueInstance = new Counter();
}
}
return uniqueInstance;
}
}
注意:.NET 2.0+ 記憶體模型保證此模式正確(volatile 或隱含柵欄)。舊版需標記 volatile。
class Program {
static void Main() {
Thread[] threads = new Thread[4];
for (int i = 0; i < 4; i++) {
int id = i;
threads[i] = new Thread(() => {
for (int j = 0; j < 4; j++) {
Counter.Instance.Increment();
Console.WriteLine($"Thread {id}: Count = {Counter.Instance.Count}");
}
});
threads[i].Name = $"Thread {i}";
threads[i].Start();
}
foreach (var t in threads) t.Join();
Console.WriteLine($"Final: {Counter.Instance.Count}"); // 應為 16
}
}