1

From the Java Memory Model specification:

An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.

The part that confuses me is this sentence:

A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.

The subject of the sentence is

A thread that can only see a reference to an object after that object has been completely initialized

The rest of the statement applies only to this subject. This suggests to me that there are some threads that can see a reference to an object before that object has been completely initialized.

If such threads exist, then the guarantee relating to final fields in this specification only applies in some cases.

In an old Brian Goetz article from 2001, Goetz describes a scenario:

Suppose thread B comes along after the memory has been allocated and the resource field is set, but before the constructor is called. It sees that resource is not null, skips the synchronized block, and returns a reference to a partially constructed Resource!

This suggests that there are in fact threads out there that can see references to objects before they are completely initialized.

Goetz then goes on to explain how using volatile doesn't help get around this problem, either.

So, how do I guarantee that some Object B cannot see some new ObjectA before ObjectA is completely initialized? It seems using final fields only helps if these conditions are already satisfied.

4

1 回答 1

0

这向我表明,在对象完全初始化之前,有一些线程可以看到对该对象的引用。

那是对的。

如果构造函数或构造函数调用的某个方法发布this到另一个线程可以看到的某个位置,则可能会发生这种情况。 Goetz 等人将此称为“不安全的出版物”(IIRC。我的这本书在约 2 公里外的书架上。)

那么,如何保证在 ObjectA 完全初始化之前,一些 Object B 看不到一些新的 ObjectA 呢?

构造ObjectA函数不应该发布this到其他线程可以看到的地方。那么一切都很好1


1 - ....对于“全部”的一些定义。我们仍然必须解决世界和平问题。

于 2018-08-30T23:23:12.737 回答