我在这里找到了以下代码:http ://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
我试图理解为什么在某些情况下这不起作用。我阅读了“微妙”问题的解释,使用volatile
将解决问题,但我有点困惑。
// Broken multithreaded version
// "Double-Checked Locking" idiom
class Foo {
private Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null) {
helper = new Helper();
}
}
}
return helper;
}
// other functions and members...
}
基本上,我是否正确地假设这会失败,因为块中的helper == null
检查synchronized
有可能失败,因为它可能是“部分”构建的?如果对象是部分构造的,java不会返回null吗?是这个问题吗?
无论如何,我知道进行双重检查锁定并不是一个很好的做法,但我只是在理论上很好奇为什么上面的代码会失败,为什么 volatile (加上分配局部变量)可以解决这个问题?这是我从某个地方得到的一些代码。
// Double-check idiom for lazy initialization of instance fields
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) { // First check (no locking)
synchronized(this) {
result = field;
if (result == null) // Second check (with locking)
field = result = computeFieldValue();
}
}
return result;
}
我知道已经有一千篇关于这个的帖子,但是解释似乎提到了 1.5 之后内存模型的变化,我也不太明白这与它有什么关系:-(。
先谢谢了!