public class Factory {
private Singleton instance;
public Singleton getInstance() {
Singleton res = instance;
if (res == null) {
synchronized (this) {
res = instance;
if (res == null) {
res = new Singleton();
instance = res;
}
}
}
return res;
}
}
这几乎是线程安全的正确实现Singleton
。我看到的唯一问题是:
The thread #1
即初始化instance
字段可以在完全初始化之前发布。现在,第二个线程可以读取instance
处于不一致的状态。
但是,对于我的眼睛来说only问题在这里。难道只是这里有问题吗?
(我们可以使instance
易挥发的)。
Shipilev 在中解释了您的示例Java 中的安全发布和安全初始化 https://shipilev.net/blog/2014/safe-public-construction/。我强烈建议阅读整篇文章,但总结一下看看UnsafeLocalDCLFactory
那里的部分:
public class UnsafeLocalDCLFactory implements Factory {
private Singleton instance; // deliberately non-volatile
@Override
public Singleton getInstance() {
Singleton res = instance;
if (res == null) {
synchronized (this) {
res = instance;
if (res == null) {
res = new Singleton();
instance = res;
}
}
}
return res;
}
}
以上存在以下问题:
这里引入局部变量是一个正确性修复,但只是部分的:在发布 Singleton 实例和读取其任何字段之间仍然没有发生之前。我们只是保护自己不返回“null”而不是 Singleton 实例。同样的技巧也可以被视为 SafeDCLFactory 的性能优化,即只执行一次易失性读取,产生:
Shipilev 建议按如下方式修复,通过标记instance
易挥发的:
public class SafeLocalDCLFactory implements Factory {
private volatile Singleton instance;
@Override
public Singleton getInstance() {
Singleton res = instance;
if (res == null) {
synchronized (this) {
res = instance;
if (res == null) {
res = new Singleton();
instance = res;
}
}
}
return res;
}
}
这个例子没有其他问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)