为什么没有 volatile 的 DCL 对原语有效?
Why DCL without volatile is valid for primitives?
免责声明:我没有在实际生产代码中使用 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
link 不为 null 但尚未初始化。发生这种情况是因为构造函数调用可能会使用 helper
link 赋值重新排序
从thread_2
来看。
但是在这篇文章中提到这种方法适用于 32 位原语。
Although the double-checked locking idiom cannot be used for
references to objects, it can work for 32-bit primitive values (e.g.,
int's or float's). Note that it does not work for long's or double's,
since unsynchronized reads/writes of 64-bit primitives are not
guaranteed to be atomic.
// 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 is broken" 比喻的实质是,使用 DCL 初始化单例对象,线程可以在看到对象处于完全初始化状态之前看到对该对象的引用。 DCL 充分同步引用单例的有效最终全局变量,但未能同步全局引用的单例对象。
在您的示例中,只有全局变量。没有"object to which it refers."
免责声明:我没有在实际生产代码中使用 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
link 不为 null 但尚未初始化。发生这种情况是因为构造函数调用可能会使用 helper
link 赋值重新排序
从thread_2
来看。
但是在这篇文章中提到这种方法适用于 32 位原语。
Although the double-checked locking idiom cannot be used for references to objects, it can work for 32-bit primitive values (e.g., int's or float's). Note that it does not work for long's or double's, since unsynchronized reads/writes of 64-bit primitives are not guaranteed to be atomic.
// 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 is broken" 比喻的实质是,使用 DCL 初始化单例对象,线程可以在看到对象处于完全初始化状态之前看到对该对象的引用。 DCL 充分同步引用单例的有效最终全局变量,但未能同步全局引用的单例对象。
在您的示例中,只有全局变量。没有"object to which it refers."