单例模式
在程序运行期间有些特殊的变量(variable)或类(calss),需要保证它们在程序中只有一个实例,才能使得程序逻辑的正确性,效率。这样的实例称之为==单例==。 单例是由设计者关心的,而不是使用者。
代码实现
单线程单例模式
非线程安全,当thread01在进行 if (_instance == null)判断时,返回true,此时thread01也进行此判断,也返回true,thread01和thread01各自创建一个对象,违背单例模式原则
/// <summary>
/// 单线程-单例模式
/// 非线程安全,当thread01在进行 if (_instance == null) 判断时,返回true,
/// 此时thread01也进行此判断,也返回true,
/// thread01和thread01各自创建一个对象,违背单例模式原则
/// </summary>
public class SingleThread_SingleTon
{
private static SingleThread_SingleTon _instance = null;
private SingleThread_SingleTon() { }
public static SingleThread_SingleTon Inst
{
get
{
if (_instance == null)
{
_instance = new SingleThread_SingleTon();
}
return _instance;
}
}
}
多线程单例模式
线程安全,对单线程单例进行加锁,保证只创建一个实例. 注意:==volatile==,此关键字用于修饰变量;在线程内存和主内存(缓存)之间同步某个变量,编译器在优化代码时候,会把常用的代码或变量加入缓存Cache中,下次再用到的时候,就优先读取Cache,这样大大提升效率;下次可能还是从Cache中读取A的值,此时A的值已经不是原来的值了,读取的就是一个脏数据,bug便随之而来。volatile 就是告诉编译器,变量A是可变的,不要加入Cache中。
/// <summary>
/// 多线程-单例模式
/// 线程安全,对单线程单例进行加锁,保证只创建一个实例
/// 注意:volatile,此关键字用于修饰变量;在线程内存和主内存(缓存)之间同步某个变量
/// 编译器在优化代码时候,会把常用的代码或变量加入缓存Cache中,下次再用到的时候,就优先读取Cache,这样大大提升效率;
/// 但是这随之产生一个问题,再多线程程序中,thread01执行后,编译器把变量A放入Cache中,thread01对变量A进行了修改,但是thread01并不知道A已经被修改,
/// 下次可能还是从Cache中读取A的值,此时A的值已经不是原来的值了,读取的就是一个脏数据,bug便随之而来。
/// volatile 就是告诉编译器,变量A是可变的,不要加入Cache中。
/// </summary>
public class MutilThread_SingleTon
{
// 注意此处的 volatile
private volatile static MutilThread_SingleTon _instance = null;
private static object _lock = new object();
private MutilThread_SingleTon() { }
public static MutilThread_SingleTon Inst
{
get
{
lock (_lock)
{
if (_instance == null)
{
_instance = new MutilThread_SingleTon();
}
}
return _instance;
}
}
}
静态单例模式
在运行期间计算变量的值,且只读,保证在程序运行期间该变量只被初始化一次
/// <summary>
/// 静态单例模式
/// static readonly 在运行期间计算变量的值,且只读,保证在程序运行期间该变量只被初始化一次
/// </summary>
public class Static_SingleTon
{
private Static_SingleTon() { }
public static readonly Static_SingleTon Inst = new Static_SingleTon();
}
本文使用 mdnice 排版