靜態(tài)類內(nèi)部加載
使用內(nèi)部類的好處是玩讳,靜態(tài)內(nèi)部類不會在單例加載時就加載蓖租,而是在調(diào)用getInstance()方法時才進行加載,達到了類似懶漢模式的效果捉片,而這種方法又是線程安全的蝙茶。
public class SingletonDemo { private static class SingletonHolder{ private static SingletonDemo instance=new SingletonDemo();
} private SingletonDemo(){
System.out.println("Singleton has loaded");
} public static SingletonDemo getInstance(){ return SingletonHolder.instance;
}
}
double check volatile
private volatile Resource resource;
public Resource getResource() {
Resource tmp = this.resource;
if (tmp == null) {
synchronized(this){
tmp = this.resource
if (tmp == null) {
this.resource = tmp = new Resource();
}
}
}
return tmp;
}
new Resource()
可以分解為:
memory =allocate(); //1:分配對象的內(nèi)存空間
ctorInstance(memory); //2:初始化對象
instance =memory; //3:設(shè)置instance指向剛分配的內(nèi)存地址
如果被重排為
memory = allocate(); //1:分配對象的內(nèi)存空間
instance = memory; //2:設(shè)置instance指向剛分配的內(nèi)存地址
ctorInstance(memory); //3:初始化對象
就會出現(xiàn)線程A中執(zhí)行這段賦值語句艺骂,在完成對象初始化之前就已經(jīng)將其賦值給resource引用,恰好另一個線程進入方法判斷instance引用不為null隆夯,然后就將其返回使用钳恕,導(dǎo)致出錯别伏。將resource設(shè)置為volatile
之后,可以保證對相關(guān)操作的順序忧额。