开发者社区> 问答> 正文

《java并发编程实战》安全发布?报错

"

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域是一个失效值,因此将看到一个空引用或者之前的旧值”,会得到旧值的呀。为什么不会出现不正确发布呢?

换句话说,书上说不可变对象在何时都是线程安全的。那么线程在初始化这个对象时,还未初始化完全,另一个线程就获取了这个对象的引用,这个时候引用是空的。这哪里安全了?

求大佬帮忙看下。。

" ![image.png](https://ucc.alicdn.com/pic/developer-ecology/c9f25a50d1f1458dac39013dfcae06ae.png)

展开
收起
因为相信,所以看见。 2020-05-25 15:58:32 945 0
1 条回答
写回答
取消 提交回答
  • 阿里,我所有的向往

    伸手就算了,连重现步骤error log都没有...不合格伸手党么...

    ![image.png](https://ucc.alicdn.com/pic/developer-ecology/79e317e2171246e3aaf12c9dbf6616d4.png)
    2020-05-26 09:47:43
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
Spring Cloud Alibaba - 重新定义 Java Cloud-Native 立即下载
The Reactive Cloud Native Arch 立即下载
JAVA开发手册1.5.0 立即下载