构造一个对象后,是否与其他线程建立了内存栅栏?

Cap*_*ngs 5 java memory concurrency constructor memory-fences

有人可以验证我对构造函数执行后建立的内存栅栏的理解.例如,假设我有一个名为Stock的类.

public final class Stock{

       private final String ticker;
       private double qty;
       private double price;

       public Stock ( String ticker, double qty, double price ){
              this.ticker  = ticker;
              this.qty     = qty;
              this.price   = price;

              //I am assuming a memory fence gets inserted here.
       }


       public final void updateQty( double qty ){
           this.qty = qty;
       }


       public final void updatePrice( double price ){
           this.price = price;
       }

}
Run Code Online (Sandbox Code Playgroud)

此外,假设构造是由执行线程1,然后updateQty()updatePrice()被称为若干时间线程2(总是由线程2).

我的论点是,在Thread1创建对象之后,对象的"可见性"与jvm中的所有其他线程建立.由于两个可变变量仅由Thread2更改,因此我不需要任何锁定.我对么?

Gra*_*ray 5

我的论点是,在Thread1创建对象之后,对象的"可见性"与jvm中的所有其他线程建立.

这是正确的.没有隐含的构造函数内存屏障/围栏,这就是构造函数周围的指令重新排序是一个问题.如果您要Stock在构造它的其他线程中使用对象,则synchronize在调用任何更新方法之前,您将不得不使用该对象.

由于两个可变变量仅由Thread2更改,因此我不需要任何锁定.

在最初同步对象之后,除非您想在其他线程中查看这些变异字段,否则Thread2不需要任何其他锁定.如果多个线程正在从您的Stock对象读取而在进行Thread2变异时,则所有线程都需要通过同步或通过使字段变异字段来跨越内存屏障volatile.

这必须同时使用构造函数操作重新排序内存可见性.有关构造函数重新排序的更多缺陷,请参阅此答案:

这是对象的安全发布吗?