Поскольку мне нужно только передавать данные между потоками в несколько контролируемых моментов времени, можно ли будет принудительно заставить все кэши выполнять обратную запись в основную память вместо использования энергозависимых полей?
Нет. Это не так, как все это работает. Позвольте мне дать вам очень короткие ответы, чтобы объяснить, почему вы думаете об этом неправильно:
1.a) Может ли рабочий поток после запуска видеть старые игровые данные, потому что основной поток может работать на другом ядре, которое кэшировало некоторые из его результатов?
Конечно. Или это может быть по какой-то другой причине. Видимость памяти не гарантируется, поэтому вы не можете полагаться на нее, если не используете что-то гарантированное для обеспечения видимости памяти.
1.b) Если вышеприведенное верно: нужно ли мне объявлять каждое поле в данных игры как изменчивое, чтобы защитить себя с абсолютной гарантией от противоречивых данных?
Нет. Любой метод обеспечения видимости памяти будет работать. Вам не нужно делать это каким-то особым образом.
2) Правильно ли я полагаю, что производительность получит нетривиальный удар, если все поля будут нестабильными?
Возможно. Вероятно, это был бы худший из возможных способов сделать это.
3) Поскольку мне нужно только передавать данные между потоками в несколько и хорошо контролируемых моментов времени, можно ли будет принудительно заставить все кэши выполнять обратную запись в основную память вместо использования энергозависимых полей?
Нет. Поскольку нет операции «записать кэш обратно в память», которая обеспечивает видимость памяти. Ваша платформа может даже не иметь таких кэшей, и проблема может быть совсем в другом. Вы пишете код Java, вам не нужно думать о том, как работает ваш конкретный процессор, какие у него ядра или кэши или что-то в этом роде. Это одно из больших преимуществ использования языка с семантикой, которая гарантирована и не говорит о ядрах, кешах или чем-то подобном.
4) Есть ли лучший подход? Возможно, моя концепция плохо продумана?
Абсолютно. Вы пишете код Java. Используйте различные классы и функции синхронизации Java и полагайтесь на них, чтобы доказать семантику, которую они задокументировали. Даже не думайте о ядрах, кешах, сбросе памяти или чем-то подобном. Это аппаратные детали, о которых вам, как программисту на Java, даже не нужно думать.
Любая Java-документация, в которой говорится о ядрах, кэшах или сбросах в память, на самом деле не говорит о реальных ядрах, кэшах или сбросах в память. Это просто дает вам несколько способов подумать о гипотетическом оборудовании, чтобы вы могли обдумать, почему видимость памяти и общий порядок не всегда работают идеально сами по себе. Ваш реальный процессор или платформа могут иметь совершенно разные проблемы, которые не имеют никакого сходства с этим гипотетическим оборудованием (А у реальных процессоров и систем согласованность кэша гарантируется аппаратными средствами, и их проблемы с отображением / упорядочением на самом деле совершенно разные!)