一、单例模式介绍
单例模式(Singleton Pattern) 是一种创建型设计模式,++它确保一个类只有一个实例,并提供一个全局访问点++。这个模式在需要一个对象被共享且全局唯一的情况下非常有用,比如配置对象、日志对象、数据库连接对象等。
单例模式的主要作用包括:
- 提供全局唯一的访问点,方便代码调用和管理。
- 避免不必要的内存开销和资源浪费,因为只有一个实例存在。
- 提高代码的可维护性和可扩展性,因为修改单例对象的行为非常方便。
然而,单例模式也存在一些缺点,如可能导致职责过多 、线程安全问题 和测试困难等。因此,在使用单例模式时需要谨慎考虑其适用场景和潜在问题。
二、单例模式代码实现
在C#中,单例模式的实现方法有多种,常见的包括:
1. 饿汉式 (Eager Initialization)
饿汉式在类加载时就创建实例,线程安全但可能浪费资源(如果实例从未被使用)。
cs
public sealed class SingletonEager
{
private static readonly SingletonEager _instance = new SingletonEager();
// 私有构造函数防止外部实例化
private SingletonEager()
{
}
//其他类通过SingletonEager.Instance来调用这个类的唯一实例
public static SingletonEager Instance
{
get { return _instance; }
}
// 其他方法和属性...
}
2. 懒汉式 (Lazy Initialization)
懒汉式在第一次使用时才创建实例,但需要注意线程安全问题。这里为了预防线程安全,加了一个lock。在多线程调用这个类的单例时,先得到lock的线程调用实例时,其他线程会等待。
cs
public class SingletonLazy
{
// volatile确保当instance变量被初始化成Instance时,多个线程能够正确处理instance变量
private static volatile SingletonLazy _instance;
// 锁定对象
private static readonly object _lock = new object();
// 私有构造函数防止外部实例化
private SingletonLazy()
{
}
public static SingletonLazy Instance
{
get
{
lock (_lock) // 加锁
{
if (_instance == null)
{
_instance = new SingletonLazy();
}
}
return _instance;
}
}
// 其他方法和属性...
}
3. 双重检查锁定 (Double-Checked Locking with volatile
)
判断两次if (_instance == null) ,在几十几百个线程都使用这个实例时就不用排队等待锁了,避免了线程堵塞。并且使用了volatile
关键字以避免指令重排序问题。
cs
public class SingletonDoubleChecked
{
// 使用volatile确保多线程正确处理instance的可见性
private static volatile SingletonDoubleChecked _instance;
// 锁定对象
private static readonly object _lock = new object();
// 私有构造函数防止外部实例化
private SingletonDoubleChecked()
{
}
public static SingletonDoubleChecked Instance
{
get
{
if (_instance == null) // 第一次检查
{
lock (_lock) // 加锁
{
if (_instance == null) // 第二次检查
{
_instance = new SingletonDoubleChecked();
}
}
}
return _instance;
}
}
// 其他方法和属性...
}