我正在查看我们的应用中的一些代码,我认为可能会遇到“Double-checked locking”的情况。我编写了一些类似于我们的示例代码。
任何人都可以看到这是如何经历双重检查锁定的吗?或者这样安全吗?
class Foo {
private Helper helper = null;
public Helper getHelper() {
Helper result;
synchronized(this) {
result = helper;
}
if (helper == null) {
synchronized(this) {
if (helper == null) {
helper = new Helper();
}
}
}
return helper;
}
}
从wiki借来的基本代码。
答案 0 :(得分:6)
这是不必要的复杂,最简单的“安全”做DCL的方式是这样的:
class Foo {
private volatile Helper helper = null;
private final Object mutex = new Object();
public Helper getHelper() {
if (helper == null) {
synchronized(mutex) {
if (helper == null) {
helper = new Helper();
}
}
}
return helper;
}
}
这里的关键点是:
this
实例上另一个代码区域同步的情况下可能出现性能损失。答案 1 :(得分:3)
双重检查锁定的重点是快速路径(当您不需要实例化对象时)不同步。所以你所拥有的不是双重锁定。
你需要摆脱第一个同步的块,以获得一个破坏的双重检查锁。然后你需要让helper
volatile来修复它。
答案 2 :(得分:0)
这部分是标准的双重检查锁定:
if (helper == null) {
synchronized(this) {
if (helper == null) {
helper = new Helper();
}
}
}
第一部分是无用的赋值,它对双重检查的锁定部分没有任何作用:如果helper为null则无论如何都会执行,如果不是,则无论如何都不会执行。它完全无效。