免责声明:我不在实际的生产代码中使用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(
thread_2
)might
看到helper
链接不为空,但尚未初始化。发生这种情况是因为构造函数调用可能会使用helper
链接分配进行重新排序来自
thread_2
veiw。但是在本文中提到,这种方法适用于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位写入是原子的。
这里局部变量的原因是什么?
最佳答案
“ DCL已损坏”的概念是,使用DCL初始化单例对象,线程可以在看到对象处于完全初始化状态之前看到对该对象的引用。 DCL充分同步了引用单例的有效最终全局变量,但无法同步全局引用的单例对象。
在您的示例中,只有全局变量。没有“它所指的对象”。