這里講的線程不安全,主要是在判斷是否創建了這個實例的代碼塊里。樓上很多贊的那個,提到的方法叫雙重檢查鎖定。
問題根源是,instance = new Instance()可以分解成三行偽代碼。正常的順序是分配對象的內存空間->初始化對象->設置instance指向剛分配的內存地址。注意第2.3步會被重排序。這時候instance被分配了內存但是沒有初始化。如果這時候有一個線程B來訪問,他判斷instance!=null后調用這個對象時發現對象沒有初始化,就出現bug了~解決方案:1、Instance聲明為volatile類型。2、允許重排序,但是重排序不被其他線程看到。
問題根源是,instance = new Instance()可以分解成三行偽代碼。正常的順序是分配對象的內存空間->初始化對象->設置instance指向剛分配的內存地址。注意第2.3步會被重排序。這時候instance被分配了內存但是沒有初始化。如果這時候有一個線程B來訪問,他判斷instance!=null后調用這個對象時發現對象沒有初始化,就出現bug了~解決方案:1、Instance聲明為volatile類型。2、允許重排序,但是重排序不被其他線程看到。
2017-03-14
public class Singleton2 {
private Singleton2() {}
private static Singleton2 instance;
public static Singleton2 getInstance() {
if (instance == null) {
synchronized (Singleton2.class) {
if (instance == null) {
instance = new Singleton2();}}}
return instance;
}
}
private Singleton2() {}
private static Singleton2 instance;
public static Singleton2 getInstance() {
if (instance == null) {
synchronized (Singleton2.class) {
if (instance == null) {
instance = new Singleton2();}}}
return instance;
}
}
2017-01-09
餓漢模式:類加載的時候便進行了創建...
額...其實是因為static代碼塊的原因
一個類運行加載進入內存的時候 首先加載static靜態代碼塊
可以搜索一下“考查靜態語句塊、語句塊以及構造函數的執行順序”
弄懂了就知道餓漢模式了
BTW:上面搜索的東西是一道Java面試題
額...其實是因為static代碼塊的原因
一個類運行加載進入內存的時候 首先加載static靜態代碼塊
可以搜索一下“考查靜態語句塊、語句塊以及構造函數的執行順序”
弄懂了就知道餓漢模式了
BTW:上面搜索的東西是一道Java面試題
2017-01-03