Будет ли объект безопасно опубликован?
1) volatile DataObject obj = new DataObject();
2) synchronized(this) {
obj = new DataObject();
}
3) synchronized(this) {
DataObject temp = new DataObject();
temp.initField1()
temp.initField2()
obj = temp
}
DataObject не является неизменяемым (имеет не финальные поля), публикуется в потоке 1 и читается в потоке 2. Чтение DataObject из второго потока не синхронизировано.
Варианты публикации 1) и 2) не являются безопасными, а будет ли безопасен вариант 3? (тут нужна гарантия видимости ссылки и состояния объекта, а также гарантии что объект не будет опубликован раньше завершения инициализации в результате реордеринга и т.п.)
Изменил вопрос чтобы не было разночтений:
final class ImmutableDataObject {
private final int field;
public ImmutableDataObject(int data) {
field = data;
}
public int getField() {
return field;
}
}
class DataObject {
private int field1;
public DataObject(int data) {
field1 = data;
}
public int getField1() {
return field1;
}
}
class DataObject2 extends DataObject {
private int field2;
public DataObject2(int data) {
super(data);
}
void initField2(int data) {
field2 = data;
}
public int getField2() {
return field2;
}
}
class Test1 {
public volatile ImmutableDataObject obj = new ImmutableDataObject(1);
}
class Test2 {
public volatile DataObject obj = new DataObject(1);
}
class Test3 {
public volatile DataObject obj;
public synchronized void init() {
obj = new DataObject(1);
}
}
class Test4 {
public volatile DataObject2 obj;
public void init() {
DataObject2 temp = new DataObject2(1);
temp.initField2(2);
obj = temp;
}
}
Test1: публикация безопасна т.к. объект неизменяемый
Test2 и Test3: публикация не безопасна т.к. внутреннее состояние объекта видимо через "гонку" и может быть любым
Test4: Комментаторы ниже сошлись на мнении, что публикация в Test4 безопасна и синхронизация не нужна т.к. объект создается локально и другие потоки не могут увидеть его в недостроенном состоянии. Запись ссылки в volatile переменную атомарна и гарантирует отсутствие переупорядочиваний со стороны компилятора и процессора т.о. другие потоки всегда будут видеть корректное состояние объекта.
Есть другое мнение или найдена ошибка? Комментарии приветствуются!!!