Java 对象引用的不当发布
下面的例子来自Brian Goetz的“Java并发实践”一书,第3章,第3.5.1节。这是对象的不当发布的示例:
class SomeClass {
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
}
public class Holder {
private int n;
public Holder(int n) { this.n = n; }
public void assertSanity() {
if (n != n)
throw new AssertionError("This statement is false");
}
}
它说持有者可能出现在另一个线程的不一致状态,而另一个线程可以观察部分构造的对象。怎么会这样?你能用上面的例子给出一个场景吗?
此外,它还继续说,在某些情况下,线程可能会在第一次读取字段时看到过时的值,然后在下次看到更新的值,这就是为什么可以抛出 .如何投掷?assertSanity
AssertionError
AssertionError
从进一步的阅读来看,解决此问题的一种方法是通过使变量最终确定来使不可变。现在,让我们假设它不是一成不变的,而是实际上是不可变的。Holder
n
Holder
为了安全地发布此对象,我们是否必须使持有者初始化成为静态的,并将其声明为易失性(静态初始化和易失性或只是易失性)?
像这样:
public class SomeClass {
public static volatile Holder holder = new Holder(42);
}