作者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