Java 'финальная' переменная экземпляра - видимость и распространение внутреннего состояния переменной - PullRequest
0 голосов
/ 04 апреля 2020

При чтении документации , связанной с потоками и блокировками, меня привлекло предложение, описывающее ключевое слово final:

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

Означает ли это, что если я объявлю final Object object = ... в качестве переменной экземпляра и затем получить к нему доступ (изменить его внутреннее состояние - object.state) из анонимных внутренних классов (несколько экземпляров Runnable), тогда значение object.state может быть фактически прочитано / записано из / в кэш ЦП и оно (значение object.state) может не совпадать c между этими Runnable экземплярами?

Так что, если я хочу быть уверен, что значение object.state правильно распространяется во всех потоках, которые я должен объявите object как volatile Object object вместо?

Спасибо.


Редактировать: я отредактировал свой оригинальный вопрос. И теперь я знаю, что неправильно понял документацию, поэтому ответ на мой последний вопрос NO - volatile/final Object object не влияет на object.state - это зависит от того, как object.state объявлен, инициализирован и / или получен доступ .

Спасибо @Burak Serdar за ответ!

Ответы [ 2 ]

3 голосов
/ 04 апреля 2020

Когда вы объявляете final Object object=..., окончательным значением является ссылка на объект, а не внутреннее состояние объекта. Это означает, что ничто не может изменить object, это не говорит о том, что ничто не может изменить, скажем, object.value. Таким образом, переменная object может быть кэширована, что не означает, что внутреннее состояние object может быть кэшировано.

0 голосов
/ 04 апреля 2020

Final не поможет вам с проблемами потоков, как вы надеетесь, извините. Volatile может помочь в некоторых ситуациях, но вам может понадобиться блокировка.

Из учебников Oracle:

-Чтения и записи являются атомами c для ссылочных переменных и для большинства примитивных переменных. (все типы кроме длинных и двойных). -Читает и записывает атомы c для всех переменных, объявленных как volatile (включая переменные long и double).

Это означает, что ваш объект не будет немедленно обновлен между операциями чтения и записи, но он будет согласован в течение одного чтения /write.

...