作者qweqweqweqwe (啪)
看板java
標題[問題] 一個 singleton? 的問題
時間Sun Dec 29 05:15:19 2013
各位板友好,最近遇到了一個跟 Singleton? 有關的問題想請教一下,
程式碼是憑印象大略打的,所以有誤的話還請見諒 QQ
class Single {
private static Single mInstance;
public static Single getInstance() {
if (mInstance == null) {
mInstance = new Single();
}
return mInstance;
}
private Single(){}
public static void reset() {
mInstance = null;
}
}
這是一個簡單的 singleton,先忽略第一次 getInstance() thread safe的問題,
這個instance會在程式內被很頻繁的使用到,
當遇到某個特別的情況時,
"必須"要把 call reset() 這個方法來讓 mInstance 重新 new,
但 call reset() 跟 call getInstance() 是不同的 thread,
由於是不同thread所以在 reset() 後 getInstance() 有機率造成 NPE,
所以我把 Single 程式稍微修改一下如下 SingleA
class SingleA {
private static SingleA mInstance;
private static final Object SYNC = new Object();
public static SingleA getInstance() {
synchronized(SYNC){
if (mInstance == null) {
mInstance = new SingleA();
}
}
return mInstance;
}
private SingleA(){}
public static void reset() {
synchronized(SYNC){
mInstance = null;
mInstance = new SingleA();
}
}
}
說到這裡,想請問的問題有幾個,
1. 想確認第一段程式碼中造成 NPE 是否真的是因為 thread unsafe的關係?
(程式碼中都會把 getInstance 用一個 local variable 存起來,
例如 Single single = Single.getInstance(); )
造成的原因是 thread 1 call getInstance 當通過 if(mInstance == null)
的判斷後 thread 2 call reset 所以導致 thread 1 最後 return null 嗎?
2. 如果問題一中我的推論是正確的 (也就是 npe 是 thread unsafe 造成的)
那請問 SingleA 這樣修改是正確(正確的定義是 thread safe) 的嗎?
3. 如果 SingleA 是 thread safe 的話,想請問有沒有其他更好的方法
可以達成呢?因為 getInstance() 會很頻繁的使用,所以不太希望
裡面會有 synchronized 。
如果有什麼不清楚的還請見諒 QQ
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.135.114.160
2F:→ qrtt1:有些東西自己寫容易錯的就儘管用抄的吧。 12/29 10:25
3F:→ qrtt1:如果不是維護舊東西,我大概都用 IoC Container 來做它。 12/29 10:27
QQ 但這是個數十萬行架構的程式碼 小弟把問題先簡化而已
在以前的情況下因為可以保證第一次new instance 是thread safe,
而且也不會把 instance 設成 null,所以以前沒遇到這種問題。
※ 編輯: qweqweqweqwe 來自: 220.135.114.160 (12/29 12:58)
4F:→ qrtt1:可是寫法就不對了,至少 getInstance 要 static 啊 12/29 13:33
5F:→ qrtt1:而且還要加 synchronized (不考慮lazy initialization的話) 12/29 13:35
喔喔 不好意思忘了打上 static , 已經補上了謝謝提醒
另外上面有提到
系統第一次 Single.getInstance() 的 initialization 時"一定保證"是 thread safe ,
所以原本的 Single.getInstance() 並不需要加上 synchronized。
※ 編輯: qweqweqweqwe 來自: 220.135.114.160 (12/29 14:04)
※ 編輯: qweqweqweqwe 來自: 36.224.104.196 (12/29 20:29)
6F:推 qrtt1:回到最初的建議,這樣隨興寫太容易出錯了。有些東西只能抄的 12/30 11:47