1. 懒汉式单例(非线程安全)
这种方式在首次使用时才创建实例,但在多线程环境下可能会创建多个实例。
public class LazySingleton
{
// 私有静态字段,用于保存单例实例
private static LazySingleton instance;
// 私有构造函数,防止外部实例化
private LazySingleton() { }
// 公共静态属性,用于获取单例实例
public static LazySingleton Instance
{
get
{
if (instance == null)
{
instance = new LazySingleton();
}
return instance;
}
}
}
2. 懒汉式单例(线程安全)
使用lock
关键字保证在多线程环境下也只创建一个实例。
public class ThreadSafeLazySingleton
{
// 私有静态字段,用于保存单例实例
private static ThreadSafeLazySingleton instance;
// 私有静态对象,用于线程同步
private static readonly object lockObject = new object();
// 私有构造函数,防止外部实例化
private ThreadSafeLazySingleton() { }
// 公共静态属性,用于获取单例实例
public static ThreadSafeLazySingleton Instance
{
get
{
lock (lockObject)
{
if (instance == null)
{
instance = new ThreadSafeLazySingleton();
}
}
return instance;
}
}
}
3. 双重检查锁定单例(线程安全)
先检查实例是否存在,若不存在再进行锁定检查,减少了锁的开销。
public class DoubleCheckedLockingSingleton
{
// 私有静态字段,用于保存单例实例
private static DoubleCheckedLockingSingleton instance;
// 私有静态对象,用于线程同步
private static readonly object lockObject = new object();
// 私有构造函数,防止外部实例化
private DoubleCheckedLockingSingleton() { }
// 公共静态属性,用于获取单例实例
public static DoubleCheckedLockingSingleton Instance
{
get
{
if (instance == null)
{
lock (lockObject)
{
if (instance == null)
{
instance = new DoubleCheckedLockingSingleton();
}
}
}
return instance;
}
}
}
4. 饿汉式单例(线程安全)
在类加载时就创建实例,天生线程安全。
public class EagerSingleton
{
// 私有静态字段,在类加载时就创建实例
private static readonly EagerSingleton instance = new EagerSingleton();
// 私有构造函数,防止外部实例化
private EagerSingleton() { }
// 公共静态属性,用于获取单例实例
public static EagerSingleton Instance
{
get
{
return instance;
}
}
}
5. 使用Lazy<T>
的单例(线程安全)
Lazy<T>
类型会在第一次访问时延迟创建实例,并且是线程安全的。
public class LazyDotNetSingleton
{
// 私有静态 Lazy<T> 对象,用于延迟创建单例实例
private static readonly Lazy<LazyDotNetSingleton> lazy = new Lazy<LazyDotNetSingleton>(() => new LazyDotNetSingleton());
// 私有构造函数,防止外部实例化
private LazyDotNetSingleton() { }
// 公共静态属性,用于获取单例实例
public static LazyDotNetSingleton Instance
{
get
{
return lazy.Value;
}
}
}
使用示例
class Program
{
static void Main()
{
// 获取单例实例
LazySingleton singleton = LazySingleton.Instance;
// 可以使用 singleton 实例进行操作
}
}
这些方法各有优劣,你可以根据具体的需求来选择合适的单例实现方式。一般而言,使用Lazy<T>
的方式是比较推荐的,因为它简洁且线程安全。