Чтобы использовать эффективно неизменяемый объект без полей final
потокобезопасным способом, необходимо использовать один из безопасных идиом публикации, когда объект становится доступным для других потоков после инициализации, в противном случае эти потоки могут видеть объект частичноинициализированное состояние (из Java-параллелизма на практике ):
- Инициализация ссылки на объект из статического инициализатора;
- Сохранение ссылки на него вvolatile field или AtomicReference;
- Сохранение ссылки на него в конечном поле правильно построенного объекта;или
- Сохранение ссылки на него в поле, которое должным образом защищено замком.
Объявление полей вашего неизменяемого объекта как final
снимает это ограничение (т.е.это гарантирует, что если другие потоки увидят ссылку на объект, они также увидят его final
поля в полностью инициализированном состоянии).Однако в общем случае это не гарантирует, что другие потоки смогут увидеть ссылку на объект, как только он был опубликован, поэтому вам, возможно, все же придется использовать безопасную публикацию, чтобы обеспечить его.
Обратите внимание, что если вашобъект реализует интерфейс, вы можете использовать подход, используемый Collections.unmodifiableList()
, и т. д .:
class ImmutableFooWrapper implements IFoo {
private final IFoo delegate; // final provides safe publication automatically
public ImmutableFooWrapper(IFoo delegate) {
this.delegate = delegate;
}
...
}
public IFoo immutableFoo(IFoo foo) {
return new ImmutableFooWrapper(foo);
}