单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
构成:
1.私有的构造函数
2.私有静态的实例
3.返回实例的静态方法
publicclassSingleton
{PRivatestaticSingleton uniqueInstance =newSingleton();privateSingleton() { Console.WriteLine("this is a new singleton"); }publicstaticSingleton getInstance()
{if(uniqueInstance ==null)
{returnuniqueInstance;
}returnuniqueInstance;
}
}
这种叫做饿汉模式,实例在类加载时就创建了,缺点是如果实例如果消耗大量的资源而没有使用就会造成浪费,另一种懒汉模式,实例在被使用时才创建,
publicclassSingleton
{privatestaticSingleton uniqueInstance;privateSingleton() { Console.WriteLine("this is a new singleton"); }publicstaticSingleton getInstance()
{if(uniqueInstance ==null)
{returnuniqueInstance =newSingleton();
}returnuniqueInstance;
}
}
但是这不是线程安全的
例如
classProgram {staticvoidMain(string[] args) {while(true) {
Thread t1=newThread(Test);
t1.Start();
}
}staticvoidTest() {
Singleton s=Singleton.getInstance();
}
}
执行的结果有可能是这样
程序创建了多个实例,这不是我们想要的结果,原因是某个线程if (uniqueInstance == null)语句执行后让出了使用权,当它重新获得CPU使用权的时候,可能别的CPU已经创建了实例,而它并不知道,继续执行return uniqueInstance= new Singleton();导致出现多个实例。
因此,要为方法加锁
publicclassSingleton
{privatestaticSingleton uniqueInstance;privateSingleton() { Console.WriteLine("this is a new singleton"); }privatestaticreadonlyobjectsyncRoot =newobject();publicstaticSingleton getInstance()
{lock(syncRoot)
{if(uniqueInstance ==null)
{
returnuniqueInstance =new Singleton();}
}returnuniqueInstance;
}
}
但是这又带来了一个问题,在实例已经创建完成了,但还是会有大量的线程卡在lock (syncRoot),它们都还会尝试创建实例,这降低了性能
为此,还要为此方法创建另外一个验证
publicstaticSingleton getInstance()
{if(uniqueInstance ==null)
{lock(syncRoot)
{if(uniqueInstance ==null)
{
returnuniqueInstance =new Singleton();
}
}
}returnuniqueInstance;
}
此时,当实例已经创建完成之后,各线程不再访问临界区,提高了性能
单例模式和静态类的比较
1.单例模式可以懒加载,静态类执行更快(为什么?),即在不同条件下二者有不同的性能表现
2.单例可以继承和override
3.单例易于模拟,利于测试
4.单例利于维护状态信息