单例模式
Singleton Pattern 限制只创建一个类型的实例
- 首先记录的是简单的单线程单例模式
public class Singleton
{
//创建静态字段作为判断实例是否存在
private static Singleton Instance;
//将默认的构造函数私有化
private Singleton()
{
}
//定义一个公有方法提供一个全局访问点
public static Singleton GetSingleton()
{
if (Instance==null)
{
return new Singleton();
}
return Instance;
}
}
思路:
1、将该类的默认构造函数私有化,使其不能通过new来创建实例;
2、创建一个该类型的字段,用来作为判断该实例是否存在的依据;
3、创建一个全局访问点(必须为静态),在该方法中作判断;
但是,在多线程的情况下,有可能多个线程同时进去到instance==null的判断语句里,就会同时创建多个实例。
- 多线程
public class Singleton
{
private static Singleton Instance;
private static readonly object obj = new object();
private Singleton()
{
}
public Singleton GetSingleton()
{
if (Instance == null)
{
lock (obj)
{
if (Instance == null)
{
return new Singleton();
}
}
}
return Instance;
}
}
疑问:为什么要通过两次if判断?
答:第一个if的作用是处理多线程的判断,试想一个情况:假如已经存在一个实例,后面所有线程创建实例的时候,就可以直接返回已存在的instance实例了,如果没有第一个if,那后面的所有线程都要在lock中排队作判断,非常消耗时间;第二个if的作用的基于lock的限制线程的作用,假如两个线程在第一个if中都判断实例为null,排队进入lock,没有第二个if的话,他们就会排队创建两个线程,达不到单例的效果。
这种实现方式称为“双重锁定”
- C#单例内联写法
public class Singleton
{
public static Singleton Instance = new Singleton();
private Singleton()
{
}
}
内联初始化其实就是把静态字段放到静态构造器去初始化。同样支持多线程环境,因为只可能有一个线程执行静态构造器。这种方法有一个弊端就是不支持参数化的实例方法。
- 补充内联知识点
public class Inline
{
private int a = 1;
}
等同于
public class Inline
{
private int a;
public Inline
{
a = 1;
}
}