C#设计模式 单例模式实现方式
在 C# 中实现单例模式有多种方式,以下为 6 种常见的 C# 单例实现方式,并说明它们的优缺点和适用场景。
1. 饿汉式(Eager Initialization)
类加载时就创建实例,线程安全。
public sealed class EagerSingleton
{private static readonly EagerSingleton instance = new EagerSingleton();// 显式静态构造函数(可选),确保在首次访问前初始化static EagerSingleton() { }private EagerSingleton() { }public static EagerSingleton Instance => instance;
}
✅ 优点:线程安全、简单
❌ 缺点:不能懒加载,可能浪费资源
2. 懒汉式(Lazy, 非线程安全)
首次调用时创建实例,但多线程下不安全(仅用于教学,不推荐生产使用)。
public sealed class LazyUnsafeSingleton
{private static LazyUnsafeSingleton instance;private LazyUnsafeSingleton() { }public static LazyUnsafeSingleton Instance{get{if (instance == null)instance = new LazyUnsafeSingleton();return instance;}}
}
❌ 不适用于多线程环境
3. 加锁懒汉式(线程安全但性能差)
每次访问都加锁,保证线程安全但效率低。
public sealed class LockedSingleton
{private static LockedSingleton instance;private static readonly object lockObj = new object();private LockedSingleton() { }public static LockedSingleton Instance{get{lock (lockObj){if (instance == null)instance = new LockedSingleton();return instance;}}}
}
✅ 线程安全
❌ 每次都加锁,性能开销大
4. 双重检查锁定(Double-Checked Locking)
兼顾懒加载和性能,线程安全。
public sealed class DoubleCheckedSingleton
{private static volatile DoubleCheckedSingleton instance;private static readonly object lockObj = new object();private DoubleCheckedSingleton() { }public static DoubleCheckedSingleton Instance{get{if (instance == null){lock (lockObj){if (instance == null)instance = new DoubleCheckedSingleton();}}return instance;}}
}
✅ 线程安全、懒加载、性能较好
⚠️ 需要 volatile 防止指令重排序(C# 中 volatile 确保内存可见性)
5. 静态内部类(C# 中用嵌套类模拟)
C# 没有 Java 那样的“静态内部类自动懒加载”语义,但可以通过 嵌套私有类 + 静态字段 实现类似效果:
public sealed class NestedSingleton
{private NestedSingleton() { }public static NestedSingleton Instance => NestedHolder.instance;private static class NestedHolder{internal static readonly NestedSingleton instance = new NestedSingleton();}
}
✅ 利用 C# 类型初始化器(Type Initializer)的懒加载和线程安全特性
✅ 推荐使用(简洁、高效、安全)
💡 C# 规范保证:静态字段的初始化在类型首次被使用时由 CLR 自动完成,且是线程安全的。
6. 使用 Lazy<T>(.NET 推荐方式)
.NET 提供了 Lazy<T> 类,天然支持线程安全的懒加载。
public sealed class LazyNetSingleton
{private static readonly Lazy<LazyNetSingleton> lazy =new Lazy<LazyNetSingleton>(() => new LazyNetSingleton());private LazyNetSingleton() { }public static LazyNetSingleton Instance => lazy.Value;
}
✅ 最简洁、最安全、最符合 .NET 习惯
✅ 可通过 LazyThreadSafetyMode 控制线程安全级别(默认是完全线程安全)
默认使用
LazyThreadSafetyMode.ExecutionAndPublication,即线程安全。
总结:C# 单例实现推荐排序
| 方式 | 懒加载 | 线程安全 | 简洁性 | 推荐度 |
|---|---|---|---|---|
Lazy<T> | ✅ | ✅ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 嵌套类(Nested Holder) | ✅ | ✅ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| 双重检查锁定 | ✅ | ✅ | ⭐⭐ | ⭐⭐⭐ |
| 饿汉式 | ❌ | ✅ | ⭐⭐⭐ | ⭐⭐ |
| 加锁懒汉式 | ✅ | ✅ | ⭐ | ⭐ |
| 非线程安全懒汉式 | ✅ | ❌ | ⭐⭐ | ❌ |
✅ 最佳实践(推荐写法)
public sealed class Singleton
{private static readonly Lazy<Singleton> lazy = new Lazy<Singleton>(() => new Singleton());private Singleton() { }public static Singleton Instance => lazy.Value;
}
这个版本:
- 线程安全
- 懒加载
- 代码简洁
- 符合 .NET 最佳实践
