如果另一个线程在“构造”期间检查someObject变量,我相信它可能(由于内存模型中的怪癖)看到部分初始化的对象.新的(作为Java 5)内存模型意味着任何最终的字段都应该被设置为它们的值,然后对象变得对其他线程可见(只要对新创建的对象的引用不会从任何其他的构造函数中转义方式),但除此之外,没有多少保证.
基本上,不要在没有适当锁定的情况下共享数据(或者由静态初始化等提供的保证):)严重的是,内存模型是非常棘手的,一般的无锁编程.尽量避免这种情况成为可能.
在逻辑上,赋值发生在构造函数运行之后 – 所以如果从同一个线程观察变量,那么在构造函数调用期间它将为空.但是,正如我所说的,有内存模式的怪异.
编辑:为了双重锁定的目的,如果您的字段是易失的,并且使用Java 5或更高版本,则可以避免这种情况.在Java 5之前,内存模式不够强大.你需要完全正确的模式.有关Java,第2版,第71项,详细信息.
编辑:这是我争辩反对亚伦的内联在一个线程中可见的推理.假设我们有:
public class FooHolder
{
public static Foo f = null;
public static void main(String[] args)
{
f = new Foo();
System.out.println(f.fWasNull);
}
}
// Make this nested if you like, I don't believe it affects the reasoning
public class Foo
{
public boolean fWasNull;
public Foo()
{
fWasNull = FooHolder.f == null;
}
}
Otherwise, three steps are required:
First, the left-hand operand is evaluated to produce a variable. If this evaluation completes
abruptly, then the assignment
expression completes abruptly for the
same reason; the right-hand operand is
not evaluated and no assignment
occurs.
Otherwise, the right-hand operand is evaluated. If this
evaluation completes abruptly, then
the assignment expression completes
abruptly for the same reason and no
assignment occurs.
Otherwise, the value of the right-hand
operand is converted to the type of
the left-hand variable, is subjected
to value set conversion (§5.1.13) to
the appropriate standard value set
(not an extended-exponent value set),
and the result of the conversion is
stored into the variable.
可以通过发生之前的关系来排序两个动作.如果一个动作发生在另一个之前,那么第一个在第二个之前是可见的并被排序.
If we have two actions x and y, we write hb(x, y) to indicate that x happens-before y.
If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).
There is a happens-before edge from the end of a constructor of an object to the start of a finalizer (§12.6) for that object.
If an action x synchronizes-with a following action y, then we also have hb(x, y).
If hb(x, y) and hb(y, z), then hb(x, z).
It should be noted that the presence of a happens-before relationship between two
actions does not necessarily imply that they have to take place in that order in an
implementation. If the reordering produces results consistent with a legal execution,
it is not illegal.
换句话说,即使在单个线程中也可能发生奇怪的事情,但不能被观察到.在这种情况下,差异是可观察的,这就是为什么我认为这是非法的.