Ответ вслух Senior Многопоточность и модель памяти обновлено

Модель памяти C++

Вопрос

Объясните модель памяти C++: зачем она нужна, что такое happens-before и чем отличаются memory_order seq_cst, acquire/release и relaxed.

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

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

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

Коротко

Без модели памяти многопоточный код непредсказуем: компилятор переставляет инструкции, процессор переупорядочивает записи через буферы, и другой поток может увидеть записи не в том порядке. Модель памяти C++ определяет, какие значения поток вправе увидеть, через отношение happens-before.

Что должно прозвучать в ответе

  • Компилятор и процессор переставляют операции, без модели нельзя рассуждать о многопоточности

  • happens-before и synchronizes-with

  • seq_cst: единый глобальный порядок, по умолчанию

  • acquire/release: публикация данных через атомик

  • relaxed: только атомарность, для счётчиков

  • Гонка данных UB; цена порядков на x86 и ARM

Что могут спросить следом

  • Почему двойная проверка с обычным указателем неверна?
  • Что такое fence (atomic_thread_fence)?

Разбор

Без модели памяти многопоточный код непредсказуем: компилятор переставляет инструкции, процессор переупорядочивает записи через буферы, и другой поток может увидеть записи не в том порядке. Модель памяти C++ определяет, какие значения поток вправе увидеть, через отношение happens-before. Его создают синхронизирующие операции: захват и освобождение мьютекса, а также атомарные операции с нужным порядком. seq_cst, порядок по умолчанию, выстраивает все такие операции в единую глобальную последовательность, рассуждать проще всего. Пара release-запись и acquire-чтение того же атомика: если чтение увидело записанное значение, всё, что поток сделал до release, видно после acquire. Так публикуют данные через флаг или указатель. relaxed даёт только атомарность самой операции, годится для счётчиков. Если обращение к обычной памяти не упорядочено happens-before с конкурирующей записью, это гонка данных и UB. На x86 acquire и release почти бесплатны, а на ARM требуют барьеров, поэтому выбор порядка важен для производительности, но начинать стоит с seq_cst.

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

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