Double Check Lock(DCL) (不推薦)
public class DCLSingleton {
private static DCLSingleton sSingleton; // 存在風(fēng)險(xiǎn)
// private volatile static DCLSingleton sSingleton; // 避免風(fēng)險(xiǎn)
private DCLSingleton() {
}
public DCLSingleton getInstance() {
if (sSingleton == null) {
synchronized (DCLSingleton.class) {
if (sSingleton == null) {
sSingleton = new DCLSingleton();
}
}
}
return sSingleton;
}
}
DCL失效問題
sSingleton = new DCLSingleton();看起來是一句代碼填具,但實(shí)際上并不是一個(gè)院子操作,這句代碼最終會(huì)被編譯成多條匯編指令,大致做了3件事情:
(1)給Singleton的實(shí)例分配內(nèi)存劳景;
(2)調(diào)用Singleton()的構(gòu)造函數(shù)誉简,初始化成員變量;
(3)將sInstance對(duì)象指向分配的內(nèi)存空間(此時(shí)sInstance就不是null了)盟广。
由于Java編譯器允許處理器亂序執(zhí)行闷串,(2)(3)執(zhí)行順序無法得到保證。如果在線程A執(zhí)行1-3-2, 在3執(zhí)行完了筋量,2執(zhí)行之前的時(shí)候烹吵,線程B調(diào)用getInstance,取走了一不為空毛甲,但沒有實(shí)例化完成的instance年叮,就會(huì)出錯(cuò)。這就是DCL失效問題玻募。
使用volatile關(guān)鍵字可以保證sInstance每次都從主內(nèi)存中讀取,避免上述問題一姿,但會(huì)犧牲一定的性能七咧。
靜態(tài)內(nèi)部類單例模式(推薦)
public class InnerClassSingleton {
private static InnerClassSingleton sInstance;
private InnerClassSingleton() {
}
private static class SingletonHolder {
private static final InnerClassSingleton sInstance = new InnerClassSingleton();
}
public InnerClassSingleton getInstance() {
return SingletonHolder.sInstance;
}
}
參考
《Android源碼設(shè)計(jì)模式解析與實(shí)戰(zhàn)》