Установлен ли забор памяти с другими потоками после создания объекта?
Может ли кто-нибудь проверить мое понимание ограничения памяти, установленного после выполнения конструктора. Например, предположим, у меня есть класс 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.
Это плохо, но это создало бесконечную путаницу для программистов.