【转】[C#] 单例模式
来自:阿里的 通义灵码
在C#中,单例模式实现线程安全时通常会采用双重检查锁定(Double-Checked Locking, DCL)的策略来确保只创建类的一个实例,并且这个过程是线程安全的。
两层lock
的设计是为了减少获取锁的开销,尤其是当类的实例已经被初始化的情况下。
以下是一个使用双重检查锁定的C#单例模式示例:
public sealed class Singleton { // 创建一个静态变量来保存唯一的 Singleton 实例。 private static volatile Singleton instance; // 创建一个对象用于同步访问Singleton实例。 private static object syncRoot = new Object(); // 私有构造函数防止其他代码通过new关键字实例化。 private Singleton() {} // 提供一个公共的静态方法来返回 Singleton 实例。 public static Singleton Instance { get { // 第一层检查:如果实例已存在,则直接返回,无需加锁。 if (instance != null) { return instance; } // 第二层检查:只有当第一次进入这里,即实例未被初始化时才需要加锁。 lock (syncRoot) { // 在锁内再次检查实例是否已被另一个线程初始化。 // 这是因为,在第一个if判断和进入lock之间可能存在竞态条件。 if (instance == null) { // 只有在这里创建实例。 instance = new Singleton(); } return instance; } } } }
为什么需要两层检查?
- 性能优化:
- 第一次检查
instance != null
可以在不加锁的情况下完成,如果实例已经初始化,那么大多数情况下可以直接返回实例,避免了不必要的锁操作带来的性能损耗。
- 第一次检查
- 线程安全性:
- 如果多个线程同时发现实例尚未创建,而只有一个线程能够进入内部的
lock
块进行初始化。如果没有第二次检查,所有线程都会创建实例,导致违反单例原则。 - 由于CLR的内存模型允许对象的构造和初始化顺序与指令执行顺序不同步,因此即使在多线程环境中,也需要在
lock
保护下进行实例化以保证线程安全。第二层检查确保了实例化操作仅执行一次。
- 如果多个线程同时发现实例尚未创建,而只有一个线程能够进入内部的
总结来说,双重检查锁定的目的在于既保证了线程安全,又尽量减少了对锁的使用频率,从而提高了程序的并发性能。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2022-03-22 [转]redis安装及设置
2019-03-22 [转]Win2012的 IIS 503 错误