[問題] 一個 singleton? 的問題

看板java作者 (啪)時間11年前 (2013/12/29 05:15), 編輯推噓2(204)
留言6則, 1人參與, 最新討論串1/3 (看更多)
各位板友好,最近遇到了一個跟 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

12/29 10:24, , 1F

12/29 10:25, , 2F
有些東西自己寫容易錯的就儘管用抄的吧。
12/29 10:25, 2F

12/29 10:27, , 3F
如果不是維護舊東西,我大概都用 IoC Container 來做它。
12/29 10:27, 3F
QQ 但這是個數十萬行架構的程式碼 小弟把問題先簡化而已 在以前的情況下因為可以保證第一次new instance 是thread safe, 而且也不會把 instance 設成 null,所以以前沒遇到這種問題。 ※ 編輯: qweqweqweqwe 來自: 220.135.114.160 (12/29 12:58)

12/29 13:33, , 4F
可是寫法就不對了,至少 getInstance 要 static 啊
12/29 13:33, 4F

12/29 13:35, , 5F
而且還要加 synchronized (不考慮lazy initialization的話)
12/29 13:35, 5F
喔喔 不好意思忘了打上 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)

12/30 11:47, , 6F
回到最初的建議,這樣隨興寫太容易出錯了。有些東西只能抄的
12/30 11:47, 6F
文章代碼(AID): #1IlpzgM2 (java)
文章代碼(AID): #1IlpzgM2 (java)