javamemoryconcurrencyconstructormemory-fences

After an object is constructed, is a memory fence established with other threads?


Could someone validate my understanding of the memory fence established after a constructor executes. For example, suppose I have a class called 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;
       }

}

Further, assume that the constructor is executed by Thread1 and then updateQty() and updatePrice() are called several time by Thread2 (always by Thread2).

My contention is that after Thread1 creates the object, the object's "visibility" is established with all the other threads in the jvm. And since the two mutable variables are only changed by Thread2, I don't need any locking. Am I correct?


Solution

  • My contention is that after Thread1 creates the object, the object's "visibility" is established with all the other threads in the jvm.

    This is not correct. There is no implied constructor memory barrier/fence which is why instruction reordering around the constructor is such a problem. If you are going to be using a Stock object in another thread other than the one that constructed it, you are going to have to synchronize on the object before calling any update methods.

    And since the two mutable variables are only changed by Thread2, I don't need any locking.

    After you initially synchronize on the object in Thread2 you would not need any additional locking unless you wanted to see those mutated fields in other threads. If multiple threads are reading from your Stock object while Thread2 is mutating it then all threads need to cross a memory barrier either through synchronization or by making the fields mutated fields volatile.

    This has to do both with constructor operation reordering and memory visibility. See this answer for more of the pitfalls around constructor reordering:

    Is this a safe publication of object?