一尘不染

安全发布对象的最终vs易失性担保

java

从实践中的Java并发性书中:

为了安全地发布对象,必须同时使对该对象的引用和该对象的状态对其他线程可见。可以通过以下方式安全地发布正确构造的对象:

  • 从静态初始化程序初始化对象引用

  • 将对它的引用存储到volatile字段或AtomicReference中

  • 将对其的引用存储到正确构造的对象的最终字段中

  • 将对它的引用存储到由
    锁适当保护的字段中。

我的问题是:

  1. 项目符号点2和3之间有什么区别?我对volatile方法和final方法在安全发布对象方面的区别感兴趣。
  2. 在点3中, 正确构造的物体 的最终场 他意味着什么?在开始要点之前,作者已经提到他们正在谈论一个正确构造的对象(我认为不会让this引用转义)。但是他们又为什么提到适当构造的对象呢?

阅读 232

收藏
2020-12-03

共1个答案

一尘不染

项目符号点2和3之间有什么区别?

  • volatile基本上意味着对该字段的任何写入都将从其他线程可见。因此,当您将字段声明为volatile:时private volatile SomeType field;,可以确保如果构造函数向该field:写入内容,则field = new SomeType();其他随后尝试读取的线程将看到此分配field
  • final具有相似的语义:如果有一个final字段,则可以保证:private final SomeType field;对该字段的写入(在声明中或在构造函数中): 如果对象正确,field = new SomeType();将不会重新编写该字段,并且其他线程可以看到该字段 已发布this例如,无法逃脱)。

显然,主要区别在于,如果该字段为final,则只能分配一次。

在点3中,正确构造的物体的最终场对他意味着什么?

例如,如果让您this脱离构造函数,则最终语义所提供的保证将消失:观察线程可能会看到具有其默认值的字段(对象为null)。如果对象构造正确,则不会发生。


人为的例子:

class SomeClass{
    private final SomeType field;

    SomeClass() {
        new Thread(new Runnable() {
            public void run() {
                SomeType copy = field; //copy could be null
                copy.doSomething(); //could throw NullPointerException
            }
        }).start();
        field = new SomeType();
    }
}
2020-12-03