1.關于雙檢測鎖定DCL的問題
public class SingletonKerriganD {
/**
* 單例對象實例
*/
private static SingletonKerriganD instance = null;
public static SingletonKerriganD getInstance() {
if (instance == null) {
synchronized (SingletonKerriganD.class) {
if (instance == null) {
instance = new SingletonKerriganD(); //A
}
}
}
return instance;
}
}
A處的代碼的匯編大致執(zhí)行如下幾步
1.分配內存
2.初始化
3.變量指向這個內存
在java上由于支持處理器亂序執(zhí)行春塌,2和3的順序是不定的塑径,假如3先執(zhí)行了才沧,那么第二個線程在訪問的時候會因為變量不為空直接返回忽媒,但這時還沒有初始化注竿,所以可以遇見的一定會報錯辰妙。
在c語言中是可行的压状,在java1.5以后呢引入了volatile 仆抵,volatile修飾的變量,保證每次都從堆中讀取种冬,保證在2镣丑,3沒有完全執(zhí)行完的時候不會有人可以訪問到他。會影響一定的效率
那么可以采用內部靜態(tài)類的方式娱两。
public class SingletonKerrigan implements Serializable {
private static class SingletonHolder {
/**
* 單例對象實例
*/
static final SingletonKerrigan INSTANCE = new SingletonKerrigan();
}
public static SingletonKerrigan getInstance() {
return SingletonHolder.INSTANCE;
}
/**
* private的構造函數用于避免外界直接使用new來實例化對象
*/
private SingletonKerrigan() {
}
/**
* readResolve方法應對單例對象被序列化時候
*/
private Object readResolve() {
return getInstance();
}
}