3.5 安全发布
3.5.1 不正确的发布
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.");
}
}
由于没有使用同步来确保Holder对象对其他线程可见,因此将Holder称为“未被正确发布”。在未被正确发布的对象中存在两个问题。
① 首先,除了发布对象的线程外,其他线程可以看到的Holder域是一个失效值,因此将看到一个空引用或者之前的旧值。
② 然而,更糟糕的情况是,线程看到Holder引用的值是最新的,但Holder状态的值却是失效的。
③ 情况变得更加不可预测的是,某个线程在第一次读取域时得到失效值,而再次读取这个域时会得到一个更新值,这也是assertSainty抛出AssertionError的原因。
问题:注释中说“如果将n声明为final类型,就不会出现不正确发布的问题”。将n设为final类型,那①不是照样会发生吗?“除了发布对象的线程外,其他线程可以看到的Holder域是一个失效值,因此将看到一个空引用或者之前的旧值”,会得到旧值的呀。为什么不会出现不正确发布呢?
换句话说,书上说不可变对象在何时都是线程安全的。那么线程在初始化这个对象时,还未初始化完全,另一个线程就获取了这个对象的引用,这个时候引用是空的。这哪里安全了?
求大佬帮忙看下。。