Я знаю, что модель памяти JVM предназначена для наименьшего общего знаменателя процессоров, поэтому она должна предполагать самую слабую возможную модель процессора, на котором может работать JVM (например, ARM).
Это неправильно. JMM возникла в результате компромисса между множеством конкурирующих сил: стремлением к более слабой модели памяти, чтобы программы могли работать быстрее на оборудовании со слабыми моделями памяти; желание авторов компиляторов разрешить определенные оптимизации; и стремление к тому, чтобы результат параллельных Java-программ был корректным и предсказуемым, а по возможности (!) понятным Java-программистам. См. CACM Сариты Адве. статью с общим обзором проблем с моделями памяти.
Учитывая, что x64 имеет довольно сильную модель памяти, какие методы синхронизации я могу игнорировать, предполагая, что моя программа будет работать только на процессорах [x64]?
Никто. Проблема в том, что модель памяти применяется не только к базовому оборудованию, но и к JVM, выполняющей вашу программу, и в основном к JIT-компилятору JVM. Компилятор может принять решение о применении определенных оптимизаций, разрешенных в рамках модели памяти, но если ваша программа делает необоснованные предположения о поведении памяти на основе базового оборудования, ваша программа не сработает.
Вы спрашивали о x64 и атомарной 64-битной записи. Возможно, на x64-машине разрыва слов никогда не произойдет. Сомневаюсь, что какой-либо JIT-компилятор в целях оптимизации разорвал бы 64-битное значение на 32-битные записи, но кто знает. Однако кажется маловероятным, что вы могли бы использовать эту функцию, чтобы избежать синхронизации или изменчивых полей в вашей программе. Без них записи в эти переменные могут никогда не стать видимыми для других потоков, или они могут быть произвольно переупорядочены по отношению к другим записям, что может привести к ошибкам в вашей программе.
Мой совет - сначала правильно применить синхронизацию, чтобы ваша программа была правильной. Вы можете быть приятно удивлены. Операции синхронизации были сильно оптимизированы и в общем случае могут быть очень быстрыми. Если вы обнаружите узкие места, рассмотрите возможность использования таких оптимизаций, как разделение блокировки, использование volatile или преобразование в неблокирующие алгоритмы.
ОБНОВЛЕНИЕ
ОП обновил вопрос, чтобы уточнить использование volatile
вместо блокировок и синхронизации.
Оказывается, volatile
имеет не только семантику видимости памяти. Это также делает long
и double
доступ атомарным, чего нельзя сказать о не-5_ переменных этих типов. См. раздел JLS 17.7. Вы должны иметь возможность полагаться на volatile
для обеспечения атомарности на любом оборудовании, а не только на x64.
Пока я этим занимаюсь, дополнительную информацию о модели памяти Java см. в стенограмме выступления JMM Pragmatics Алексея Шипилева. . (Алексей также является парнем JMH.) В этом докладе много подробностей и несколько интересных упражнений. чтобы проверить свое понимание. Один общий вывод из разговора заключается в том, что часто бывает ошибкой полагаться на свою интуицию в отношении того, как работает модель памяти, например. с точки зрения строк кэша или буферов записи. JMM — это формализм операций с памятью и различных ограничений (синхронизируется с, происходит до и т. д.), определяющих порядок этих операций. . Это может привести к совершенно нелогичным результатам. Неразумно пытаться перехитрить JMM, думая о конкретных аппаратных свойствах. Он вернется, чтобы укусить вас.
person
Stuart Marks
schedule
26.07.2014