我正在学习Singleton Pattern。在msdn上,Singleton Pattern的第一个实现是:
public class Singleton
{
private static Singleton instance;
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
public void Display()
{
Console.WriteLine("This is from Singleton!");
}
}
但是,这种实现的主要缺点是它对多线程环境不安全。如果单独的执行线程同时进入Instance属性方法,则可以创建更多的Singleton对象的一个实例。
我尝试创建此类的两个实例:
Console.WriteLine("First Instance!");
Singleton s = Singleton.Instance;
s.Display();
Console.WriteLine("Second Instance!");
Singleton ss = Singleton.Instance;
ss.Display();
Console.ReadLine();
“s”和“ss”都被创建,所以我想我误解了一些东西。 你能告诉我为什么要创建两个实例吗?
答案 0 :(得分:4)
在这种情况下,您不会创建两个实例。而是创建指向同一实例的两个变量。第一个调用Singleton s = Singleton.Instance;
创建实例。第二个调用只返回相同的实例。如果你给singleton类另一个字段(让我们称之为字符串文本)然后调用s.text = "a";
ss.text
也会有值" a&#34 ;;
为了使整个事情线程安全,你可以看一下Mutex类。例如。
答案 1 :(得分:2)
在代码段中,只有当单个线程始终访问模块时,if(instance == null)
检查才能创建该类的单个实例。
但是在多线程环境的情况下,它将失败并将导致Singleton类的多个实例。
假设T1和T2是两个在某个时刻同时访问get方法的线程。
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
解释如下:
if(instance == null)
时,如果实例尚未初始化则输入if if。if(instance == null)
行,就在T1进入块时(T1尚未执行instance = new Singleton()
)if
块内。Singleton
Class的差异实例。这里使用多个线程的正确方法如下 -
get
{
if (instance == null)
{
lock();
if (instance == null)
{
instance = new Singleton();
}
unlock();
}
return instance;
}
答案 2 :(得分:0)
两个(甚至更多)单独的线程可以同时进行if (instance == null)
检查。如果实例尚不存在,则两个检查都将返回true
。然后两个线程都会更进一步,每个线程都会创建自己的类实例。