Подтвердить что ты не робот

Почему переменная-член объекта не может быть как окончательной, так и изменчивой в Java?

Если в классе у меня есть экземпляр ConcurrentHashMap, который будет изменен и прочитан несколькими потоками, я могу определить так:

public class My Class {

    private volatile ConcurrentHashMap<String,String> myMap = new ConcurrentHashMap<String,String>();
...
}

добавление final в поле myMap приводит к ошибке, говорящей, что я могу использовать только final или volatile. Почему это может быть не только?

4b9b3361

Ответ 1

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

Ответ 2

Это из-за модели памяти Java (JMM).

По сути, когда вы объявляете поле объекта как final, вам нужно инициализировать его в конструкторе объекта, а затем поле final не изменит его значение. И JMM promises, что после завершения ctor любой поток увидит то же (правильное) значение поля final. Таким образом, вам не нужно использовать явную синхронизацию, такую ​​как synchronize или Lock, чтобы разрешить всем потокам видеть правильное значение поля final.

Когда вы объявляете поле объекта как volatile, значение поля может меняться, но при каждом чтении значения из любого потока будет отображаться последнее значение, записанное в него.

Таким образом, final и volatile достигают той же цели - видимость значения поля объекта, но сначала специально используется для переменной, которая может быть назначена только один раз и второй для переменной, которая может быть изменена многократно.

Ссылки:

Ответ 3

Потому что volatile и final являются двумя крайними концами в Java

volatile означает, что переменная привязана к изменениям

final означает, что значение переменной никогда не изменится вообще

Ответ 4

Поле

A volatile дает вам гарантии того, что происходит при его изменении. (Нет объекта, на который он мог бы ссылаться)

Поле

A final не может быть изменено (что может быть изменено ссылкой на поля)

Нет смысла иметь оба.

Ответ 5

volatile используется для переменных, которые могут изменяться в некоторых случаях, в противном случае нет необходимости в volatile, а final означает, что переменная может не измениться, поэтому нет необходимости в volatile.

Ваши проблемы concurrency важны, но если HashMap volatile не решит проблему, для обработки проблем concurrency вы уже используете ConcurrentHashMap.

Ответ 6

Потому что это не имеет никакого смысла. Volatile влияет на ссылочное значение объекта, а не на поля объекта и т.д.

В вашей ситуации (у вас есть параллельная карта) вы должны сделать поле final.

Ответ 7

Модификатор

volatile гарантирует, что все чтения и записи переходят в основную память, т.е. как доступ к переменной почти в блок synchronized. Это не имеет значения для конечной переменной, которая не может быть изменена.