Выбор ответа Senior Потоки и Java Memory Model обновлено

False sharing

Вопрос

Два потока часто инкрементят два разных volatile long поля одного объекта, и это неожиданно медленно. В чём вероятная причина?

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: False sharing: поля в одной кеш-линии, и ядра отбирают её друг у друга. Кеш когерентен по линиям примерно по 64 байта.

Варианты ответа

  1. volatile делает каждую операцию синхронизированной на мониторе объекта
  2. False sharing: поля в одной кеш-линии, и ядра отбирают её друг у другаправильный ответ
  3. JIT отключает оптимизации для полей типа long, если они volatile
  4. Поля long читаются за две операции по 32 бита, и каждая ждёт другую

Разбор

Кеш когерентен по линиям примерно по 64 байта. Если два горячих поля в одной линии, запись одного ядра инвалидирует линию у другого, хотя логически данные разные. Лечится разнесением полей (padding, @jdk.internal.vm.annotation.Contended внутри JDK, так сделано в LongAdder). volatile не берёт монитор. Чтение volatile long атомарно по спецификации.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.

Термины по теме