Java 为什么没有volatile的DCL对原语有效?
免责声明:我不在实际生产代码中使用DCL-我只对学术感兴趣 我读过以下著名的文章: 问题声明(我的愿景):Java 为什么没有volatile的DCL对原语有效?,java,multithreading,concurrency,volatile,java-memory-model,Java,Multithreading,Concurrency,Volatile,Java Memory Model,免责声明:我不在实际生产代码中使用DCL-我只对学术感兴趣 我读过以下著名的文章: 问题声明(我的愿景): // Correct multithreaded version class Foo { private Helper helper = null; public synchronized Helper getHelper() { if (helper == null) helper = new Helper(); return helper;
// 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...
}
让我们设想线程1执行行helper=newhelper()代码>
另一个线程(Thread_2
)可能会看到helper
链接不是空的,但尚未初始化。这是因为构造函数调用可能会使用helper
链接分配重新排序
从thread_2
vew
但在本文中提到,这种方法适用于32位原语
尽管双重检查锁定习惯用法不能用于
引用对象时,它可以用于32位基本值(例如。,
整数或浮点)。请注意,它不适用于长时间或双时间,
因为64位原语的非同步读/写不是
保证是原子的
请解释一下它为什么有效?我知道32位写入是原子的
局部变量出现的原因是什么?使用“DCL被破坏”这个比喻的本质是,使用DCL初始化单例对象,线程可以在看到处于完全初始化状态的对象之前看到对该对象的引用。DCL充分同步引用单例的最终有效全局变量,但无法同步全局引用的单例对象
在您的示例中,只有全局变量。没有“它所指的对象”
// 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...
}