final
означает, что после инициализации значение не может быть изменено.
После того, как была назначена окончательная переменная, она всегда содержит одно и то же значение. Если конечная переменная содержит ссылку на объект, то состояние объекта может быть изменено операциями над объектом, но переменная всегда будет ссылаться на один и тот же объект. https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4
так что если вы не переназначить myObjectFinal
, ничего плохого не случится,
Однако если изменить один и тот же объект из нескольких потоков, то потребуется синхронизации. (не использовать volatile
)
Прежде всего, избавитесь от объектной ориентации. Объекты - это виртуальная конструкция. мы говорим о низкоуровневых материалах, таких как регистры и кеши, - есть только примитивы (каждый класс может быть сведен к набору примитивов)
Причина, по которой нам нужны кеши, проста. Память просто ужасна медленно. Таким образом, идея состоит в том, чтобы сократить количество обращений к памяти до минимума.
рассмотрим следующий код:
1. x=0;
2. if (x == 1)
3. x++
внутри обычного компьютера происходит сейчас что-то вроде этого (без регистра-оптимизации)
1. write 0 into a register
write the register into the memory
2. read x from the memory into a CPU-register
compare it with 1 and go to 3 or 4
3. read x from the memory into a CPU-register
increment register
write the register into the memory
много избыточных операций памяти ... но вы могут их устранить
1. write 0 into a register
write the register into the memory
2. compare the register with 1 and go to 3 or 4
3. increment register
write the register into the memory
Мы храним значение x в регистре стер. Так почему бы не сохранить все переменные в реестрах? в первую очередь, существует множество доступных регистров, поэтому вы не можете хранить все там. Это скорее временная вещь для хранения переменной в регистре.(например, внутри области) Другая проблема заключается в том, что никакое другое ядро и/или устройство не могут считывать из регистров. то вам нужно перезагрузить/записать переменную.
Если вы объявите переменную окончательной, она никогда не будет изменена. Таким образом, переменная может храниться в регистре без проблем с несогласованностью. Однако это не означает, что другие потоки не могут получить доступ к переменной, поскольку она также хранится внутри памяти. Он гарантирует, что значение в памяти всегда действует. Но все переменные, независимо от того, являются ли они окончательными или нет, могут и будут храниться в течение короткого времени в регистрах. поэтому нам нужно использовать инструмент синхронизации, который заставляет обратную запись из регистров в память, если вы хотите гарантировать согласованность нескольких потоков/ядер.
однако реальный кэш-память процессора - это совершенно другая тема. его полная прозрачная система (выполняется на стороне аппаратного обеспечения!), на которую влияет только шаблон доступа к памяти (если только вы действительно не делаете сумасшедший низкоуровневый уровень в сборке). Чтобы сделать это коротко: CPU-cache в основном кэширует каждый байт, если вы явно не заставляете его не делать этого.
Ваш вопрос скорее о ключевом слове 'volatile', чем о' final'. Если ваша переменная (member) объявлена 'volatile', JVM будет считать, что изменения в других потоках видны в текущем потоке. без ключевого слова 'volatile' это не будет, без ключевого слова' final'. –
** У меня есть объект myObjectFinal, установленный как final ** - Нет, у вас нет 'Object', установленного как' final', у вас есть ** Object Reference ** установлен как 'final'. Как правило, 'volatile' и' final' имеют смысл для видимости примитивных типов и других сценариев, требуют явной «синхронизации». –
@Sabir Очевидно, что я помещаю окончательный вариант в ссылку на объект! Мой вопрос не имеет смысла, если я буду копировать объект или использовать примитивы. Ваш комментарий не помогает вообще. И снова Синхронизация отличается от изменчивости. Этот вопрос касается кэширования в CPU, не делающего часть кода атомарной. – chris