Установлен ли забор памяти с другими потоками после создания объекта?

Может ли кто-нибудь проверить мое понимание ограничения памяти, установленного после выполнения конструктора. Например, предположим, у меня есть класс 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;
       }

}

Далее предположим, что конструктор выполняется Thread1, а затем updateQty() а также updatePrice() Вызываются несколько раз Thread2 (всегда Thread2).

Я утверждаю, что после того, как Thread1 создает объект, "видимость" объекта устанавливается со всеми другими потоками в jvm. И поскольку две изменяемые переменные изменяются только в Thread2, мне не нужна блокировка. Я прав?

2 ответа

Решение

Я утверждаю, что после того, как Thread1 создает объект, "видимость" объекта устанавливается со всеми другими потоками в jvm.

Это не правильно. Не существует подразумеваемого барьера / ограждения памяти конструктора, поэтому переупорядочивание команд вокруг конструктора является такой проблемой. Если вы собираетесь использовать Stock объект в другом потоке, отличном от того, который его построил, вам придется synchronize на объекте перед вызовом любых методов обновления.

И поскольку две изменяемые переменные изменяются только в Thread2, мне не нужна блокировка.

После первоначальной синхронизации на объекте в Thread2 вам не понадобится дополнительная блокировка, если вы не хотите видеть эти измененные поля в других потоках. Если несколько потоков читают из вашего Stock объект пока Thread2 мутирует, тогда все потоки должны пересекать барьер памяти либо путем синхронизации, либо путем изменения полей volatile,

Это связано как с переупорядочением операций конструктора, так и с видимостью памяти. Посмотрите этот ответ для большего количества ловушек вокруг переупорядочения конструктора:

Это безопасная публикация объекта?

К сожалению нет. Конструктор (в основном) похож на обычный метод в модели памяти Java.

Это плохо, но это создало бесконечную путаницу для программистов.

Другие вопросы по тегам