Модель памяти C++
Вопрос
Объясните модель памяти C++: зачем она нужна, что такое happens-before и чем отличаются memory_order seq_cst, acquire/release и relaxed.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Компилятор и процессор переставляют операции, без модели нельзя рассуждать о многопоточности
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 ошибок.
Ещё по теме «Многопоточность и модель памяти»
- Найти потенциальный дедлок по порядку захвата мьютексов
- Пул потоков: кто и когда выполнит задачу
- Публикация данных через флаг
- Ловушка std::async
- Потокобезопасная ленивая инициализация
- compare_exchange
- Ожидание на condition_variable
- Что такое гонка данных