Если у меня есть объект, который разделяется между потоками, мне кажется, что каждое поле должно быть либо final
либо volatile
со следующими соображениями:
-
если поле должно быть изменено (указать на другой объект, обновить значение примитива), то поле должно быть
volatile
чтобы все другие потоки работали с новым значением. Синхронизация методов, обращающихся к указанному полю, недостаточна, поскольку они могут возвращать кэшированное значение. -
если поле никогда не изменится, сделайте его
final
.
Однако я не смог ничего найти по этому поводу, поэтому мне интересно, является ли эта логика ошибочной или просто слишком очевидной?
EDIT, конечно, вместо volatile можно использовать final AtomicReference
или аналогичный.
РЕДАКТИРОВАТЬ, например, см. Является ли метод getter альтернативой volatile в Java?
РЕДАКТИРОВАТЬ, чтобы избежать путаницы: Этот вопрос о недействительности кэша! Если два потока работают с одним и тем же объектом, поля объектов можно кэшировать (для каждого потока), если они не объявлены как энергозависимые. Как я могу гарантировать, что кеш недействителен правильно?
ЗАКЛЮЧИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ Спасибо @Peter Lawrey, который указал мне на JLS §17 (модель памяти Java). Насколько я вижу, это говорит о том, что синхронизация устанавливает отношение между операциями, которое происходит до того, что поток увидит обновления из другого потока, если эти обновления произошли до того, например, если получатель и установщик для энергонезависимого поля synchronized
.