免责声明::我不在实际的生产代码中使用DCL-我只是出于学术兴趣。
我读过以下著名的文章:The "Double-Checked Locking is Broken" Declaration
问题声明(我的看法):
// Correct multithreaded version
class Foo {
private Helper helper = null;
public synchronized Helper getHelper() {
if (helper == null)
helper = new Helper();
return helper;
}
// other functions and members...
}
让我们想象 thread_1 执行了第helper = new Helper();
行
另一个线程(thread_2
)might
看到helper
链接不为空,但尚未初始化。发生这种情况是因为可能会使用helper
链接分配对构造函数调用进行重新排序
来自thread_2
面。
但是在本文中提到,这种方法适用于32位基元。
尽管双重检查锁定习惯用法不能用于 引用对象,它可以用于32位原始值(例如, 整数或浮点数)。请注意,它不适用于长整数或双精度数, 因为不同步对64位原语的读取/写入不是 保证是原子的。
// Correct Double-Checked Locking for 32-bit primitives
class Foo {
private int cachedHashCode = 0;
public int hashCode() {
int h = cachedHashCode;
if (h == 0)
synchronized(this) {
if (cachedHashCode != 0) return cachedHashCode;
h = computeHashCode();
cachedHashCode = h;
}
return h;
}
// other functions and members...
}
请向我解释为什么会起作用?我知道32位写入是原子的。
这里的局部变量是什么原因?
答案 0 :(得分:1)
“ DCL损坏”的基本概念是,使用DCL初始化单例对象,线程可以在看到对象处于完全初始化状态之前看到对该对象的引用。 DCL可以充分同步指向单例的有效最终全局变量,但无法同步全局所指的单例对象。
在您的示例中,只有全局变量。没有“它所指的对象”。