C# 之单例模式
2021-01-14 02:14
标签:sea 不能 并发 循环 第一个 不同 public 取出 决定 一、介绍: 单例的实现,有四个共同特征: 请注意:所有这些实现还使用公共静态属性Instance 作为访问实例的方法。在所有情况下,可以轻松将属性转换为方法,而不会影响线程安全和性能。 二、单例的6个常见版本: 上面代码,不是线程安全的,两个不同线程都去竞争 if(instance == null) 时候,然后发现为true,会同时创建两个实例,这违反了单例原则。为了防止这种情况,我们想到了互斥锁,保证两个线程不会共同创建实例,请看第二个版本。 上述实现时线程安全的,加锁之后,防止多线程并发创建重复对象,但它有性能缺陷,因为每次使用Instance 调用实例时,都需要去判断锁,这样导致性能有影响,于是我们想到了第三个版本,双重判断加锁。 该实现是线程安全的,不必每次都取出锁,即当第一次创建完实例后,下一次在调用实例,则不必再取出锁了。但该模式有四个缺点 为什么说他不太懒惰?因为所谓懒惰是指我们要在调用实例时才去判断是否创建实例instance,然而这里,在类里先创建了实例。 为什么说他是线程安全的?因为 C# 中静态构造函数仅在 创建类的实例 或 引用类的静态成员时执行,举个例子,例如我在调用Instance 这个实例时,会执行第一句 instance = new Singleton4(),当我第二次再调用Instance 使用静态实例时,它则不会重复创建实例,所以它是线程安全的。 上述代码是懒惰的,因为在封闭类中调用子类的instance时才去创建实例,而不是像第四个版本那样先创建了实例。请注意,尽管嵌套类可以访问封闭类中的私有成员,但是封闭类不能访问嵌套类内层,所以这里的嵌套类实例需要使用internal 关键字声明。 这里使用.NET4 或者更高版本,可以使用System.Lazy 这个类型声明懒惰的,线程安全的单例,同时他的性能非常好。 三、懒惰与性能 在许多情况下,其实不需要完全懒惰,除非您的初始化做了一些特别耗时的事情,或者其他地方产生了一些副作用,否则最好忽略上面所示的显示静态构造函数。这可以提高性能,因为它允许JIT编译器进行一次检查(例如在方法的开头)以确保类型已经初始化,然后从那时开始设定它。如果在相对紧密的循环中引用单例实例,则会产生(相对)显著的性能差异。您应该决定是否需要完全延迟实例化,并在类中适当地记录此决策。 参考原文:https://www.cnblogs.com/leolion/p/10241822.html C# 之单例模式 标签:sea 不能 并发 循环 第一个 不同 public 取出 决定 原文地址:https://www.cnblogs.com/vpersie2008/p/12272696.html
public sealed class Singleton1
{
private static Singleton1 instance = null;
private Singleton1() { }
public static Singleton1 Instance
{
get
{
if (instance == null)
{
instance = new Singleton1();
}
return instance;
}
}
}
public sealed class Singleton2
{
private static Singleton2 instance = null;
private static readonly object padlock = new object();
Singleton2() { }
public static Singleton2 Instance
{
get
{
lock (padlock)//加锁,保证两个线程并发时,不会重复创建对象,但问题是每次线程运行还得检查锁(性能略差)
{
if (instance == null)
{
instance = new Singleton2();
}
return instance;
}
}
}
}
public sealed class Singleton3
{
private static Singleton3 instance = null;
private static readonly object padlock = new object();
Singleton3() { }
public static Singleton3 Instance
{
get
{
if (instance == null)
{
lock (padlock)
{
if (instance == null)
{
instance = new Singleton3();
}
}
}
return instance;
}
}
}
public sealed class Singleton4
{
private static readonly Singleton4 instance = new Singleton4();
static Singleton4() { }//显示静态构造函数告诉C# 编译器
private Singleton4() { }
public static Singleton4 Instance
{
get
{
return instance;
}
}
}
public sealed class Singleton5
{
private Singleton5() { }
public static Singleton5 Instance { get { return Nested.instance; } }//完全懒惰的,因为必须在执行这个Instance调用时,才会执行嵌套类的创建单例语句
private class Nested
{
static Nested() { }
internal static readonly Singleton5 instance = new Singleton5();//此处要为internal的,外部要访问,不能是私有的。此处在外部调用时,需要创建单例对象时创建,实现完全懒惰
}
}
public sealed class Singleton6
{
private static readonly Lazy