在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。
如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?
综上所述 我们先创建一个单线程的Singleton
public class Singleton
{
//编译器在您没有对类写构造函数时,编译器会自己生成一个无参数的构造函数
//不过如果您创建了构造函数那么系统本身得到构造函数将会被替换
//创建一个私有的构造函数 使外部无法访问,也就无法创建当前类
private Singleton()
{
}
static Singleton instance;
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
访问只需要通过,Singlton.Instance 为何称它为单线程的Singlton因为 在多个线程同一时间访问 Instance属性时,首先访问的线程在判断instance为null时则,进入创建对象实例,在创建的过程中,又一个线程对属性进行访问,此时instance还是为null ,所以会同时可能创建多个实例。我们稍作修改即可实现多线程的Singleton
public class Singleton
{
//编译器在您没有对类写构造函数时,编译器会自己生成一个无参数的构造函数
//不过如果您创建了构造函数那么系统本身得到构造函数将会被替换
public static volatile object condition = new object();
//创建一个私有的构造函数 使外部无法访问,也就无法创建当前类
private Singleton()
{
}
static Singleton instance;
public static Singleton Instance
{
get
{
//创建一个lock 对当前代码片段 做限制 同一时间只允许一条线程访问
lock (condition)
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
}
多线程的Singleton写法只有这一种吗?不其实Singleton可以扩展出很多写法。只需要保证核心是:如何控制用户使用new对一个类的实例构造器的任意调用。volatile
关键字指示一个字段可以由多个同时执行的线程修改。 出于性能原因,编译器,运行时系统甚至硬件都可能重新排列对存储器位置的读取和写入。 声明为 volatile
的字段将从某些类型的优化中排除。 详情见 微软文档https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/volatile
理解 volatile 关键字https://zhuanlan.zhihu.com/p/269031397下面我扩展几种
public class Singleton
{
public static readonly Singleton instance;
//静态构造器 可以保证多线程情况下 只有一个线程执行了静态构造器,不可能有多个线程去执行静态构造器
static Singleton()
{
//静态构造函数
//1️⃣当访问静态成员(如静态字段、静态属性或静态方法)时。
//2️⃣ 在创建类的实例之前,记住只会触发一次。
//3️⃣ 如果类没有明确定义静态构造函数,但又有静态成员被使用,编译器会自动添加一个默认的静态构造函数。
//静态构造函数通常用于执行静态成员的初始化或执行一次性的初始化逻辑。请注意,它们不能被显式调用,并且不能带有访问修饰符(如public、private等)或参数。
instance = new Singleton();
}
private Singleton() { }
}
上述的创建Singleton模式的弊端就是不支持参数传递
支持参数传递的Singleton
public class Program
{
public static void Main()
{
Singleton singleton = Singleton.Getinstance(100,200);
}
}
public class Singleton
{
private static Singleton instance;
static volatile object condition = new object();
public static Singleton Getinstance(int x, int y)
{
lock (condition)
{
if (instance == null)
{
instance = new Singleton(x, y);
}
else
{
instance.x = x; instance.y = y;
}
return instance;
}
}
int x;
int y;
private Singleton(int x, int y)
{
this.x = x;
this.y = y;
}
}