二、问题的产生
请看如下代码:
public class Animal
{
private static Animal instance = null;
private Animal()
{
}
public static Animal getInstance()
{
if (instance == null)
{
instance = new Animal();
}
return instance;
}
}
经常看到有些网友这样写。这样写在大都数情况下挺适用的。我们知道操作系统为每个独立线程安排一些CPU时间。单CPU操作系统以轮转方式向线程提供时间片,每个线程在使用完时间片后交出控制,系统再将CPU时间片分配给下一个线程,如下代码,我将使某个线程睡眠模拟线程的时间片用完。代码如下:
public static Animal getInstance()
{
if (instance == null)
{
if (Thread.CurrentThread.Name == "Thread1")
{
Thread.Sleep(2000);//模拟Thread1的时间片用完了
}
instance = new Animal();
}
return instance;
}
?
private void BeginThread()
{
Thread th = new Thread(this.Run){IsBackground=true};
th.Name = "Thread1";
th.Start();
Thread th2 = new Thread(this.Run2) {IsBackground=true };
th2.Name="Thread2";
th2.Start();
}
private void Run()
{
Animal p1 = People.Instance;
}
private void Run2()
{
Animal p2 = People.Instance;
}
如上Animal p1与Animal p2就是不同的实例。
当然了,这里只是模拟一下时间片的轮换,虽然是模拟但是却能很好的说明问题,上面的Singleton有问题,那么应该怎么写呢?
我想有2个方法:
方法一:锁机制
public class Animal
{
private static Animal instance = null;
private static object sync = new object();
private Animal()
{
}
public static Animal getInstance()
{
if (instance != null)
{
lock (sync)
{
if (instance == null)
{
instance = new Animal();
}
}
}
return instance;
}
}
我们可以通过锁住部分代码,同时间只让一个线程执行。有人要问了:为什么最外面还要用 "if (instance != null)"
因为同步操作执行时间长,也耗资源,在最外面加个判断能够更高效的实现Singleton.