不好的解法-:只適用于單線程環(huán)境
public sealed class Singleton1
{
private Singleton1()
{
}
private static Singleton1 instance = null;
public static Singleton1 Instance
{
get
{
if(instance==null)
instance=new Singleton1();
return instance;
}
}
}
設(shè)想如果兩個(gè)線程同時(shí)運(yùn)行到判斷instance是否為null的if語句套耕,并且instance的確沒有創(chuàng)建時(shí),那么兩個(gè)線程都會(huì)創(chuàng)建一個(gè)實(shí)例,此時(shí)類型Singleton1就不再滿足單例模式的要求了。
不好的解法二:雖然在多線程環(huán)境中能工作,但效率不高
public sealed class Singleton2
{
private Singleton2() { }
private static readonly object syncObj=new object();
private static Singleton2 instance = null;
public static Singleton2 Instabce
{
get
{
lock (syncObj)
{
if(instance==null)
instance=new Singleton2();
}
return instance;
}
}
}
我們每次通過屬性 Instance得到Singleton2的實(shí)例毅访,都會(huì)試圖加上一個(gè)同步鎖,而加鎖是一個(gè)非常耗時(shí)的操作盘榨,在沒有必要的時(shí)候我們應(yīng)該盡量避免喻粹。
可行的解法:加同步鎖前后兩次判斷實(shí)例是否已經(jīng)存在
public sealed class Singleton3
{
private Singleton3()
{
}
private static object syncObj=new object();
private static Singleton3 instance = null;
public static Singleton3 Instance
{
get
{
if (instance == null)
{
lock (syncObj)
{
if(instance==null)
instance=new Singleton3();
}
}
return instance;
}
}
}
Singleton3用加鎖機(jī)制來確保在多線程環(huán)境下只創(chuàng)建一個(gè)實(shí)例,并且用兩個(gè) if 判斷來提高效率草巡。
強(qiáng)烈推薦的解法一:利用靜態(tài)構(gòu)造函數(shù)
C#的語法中有一個(gè)函數(shù)能夠確保只調(diào)用一次守呜,那就是靜態(tài)構(gòu)造函數(shù),我們可以利用C#這個(gè)特性實(shí)現(xiàn)單例模式如下:
public sealed class Singleton4
{
private Singleton4(){}
private static Singleton4 instance=new Singleton4();
public static Singleton4 Instance
{
get { return instance; }
}
}
在 Singleton4 中,實(shí)例 instance 并不是第一次調(diào)用屬性 Singleton4.Instance的時(shí)候創(chuàng)建查乒,而是在第一次用到Singleton4的時(shí)候就會(huì)被創(chuàng)建弥喉。
強(qiáng)烈推薦的解法二:實(shí)現(xiàn)按需創(chuàng)建實(shí)例
最后的一個(gè)實(shí)現(xiàn)Singleton5則很好地解決了Singleton4中的實(shí)例創(chuàng)建時(shí)機(jī)過早的問題:
public sealed class Singleton5
{
Singleton5()
{
}
public static Singleton5 Instance
{
get { return Nested.instance; }
}
class Nested
{
static Nested(){}
internal static readonly Singleton5 instance=new Singleton5();
}
}
說明:
在前面的 5 種實(shí)現(xiàn)單例模式的方法中,第一種方法在多線程環(huán)境中不能正常工作玛迄,第二種模式雖然能在多線程環(huán)境中正常工作但時(shí)間效率很低由境,都不是面試官期待的解法。在第三種方法中我們通過兩次判斷一次加鎖確保在多線程環(huán)境能高效率地工作蓖议。第四種方法利用C#的靜態(tài)構(gòu)造函數(shù)的特性虏杰,確保只創(chuàng)建一個(gè)實(shí)例。第五種方法利用私有嵌套類型的特性拒担,做到只在真正需要的時(shí)候才會(huì)創(chuàng)建實(shí)例嘹屯,提高空間使用效率攻询。