Выбор ответа Senior Многопоточность и модель памяти обновлено
Публикация данных через флаг
Вопрос
Поток A: data = 42; ready.store(true, std::memory_order_release);. Поток B: while (!ready.load(std::memory_order_acquire)) {} use(data);. Что гарантировано?
Попробуйте сами
Выберите вариант, и откроется разбор.
Показать ответ и разбор
Коротко
Правильный ответ: B увидит data == 42: release-запись синхронизируется с acquire-чтением. Запись data предшествует release-записи в потоке A, acquire-чтение, увидевшее true, синхронизируется с ней, и всё, что было до release, happens-before всего, что после acquire.
Варианты ответа
- B увидит
data == 42: release-запись синхронизируется с acquire-чтениемправильный ответ - Ничего:
dataне атомарна, поэтому чтение в B это гонка данных - B увидит 42, только если
dataтоже объявлена какstd::atomic<int> - Гарантия есть только на x86 с его сильной моделью памяти, на ARM нет
Разбор
Запись data предшествует release-записи в потоке A, acquire-чтение, увидевшее true, синхронизируется с ней, и всё, что было до release, happens-before всего, что после acquire. Гонки по data нет: обращения упорядочены.
dataможет быть обычной переменной, синхронизацию даёт атомарный флаг.- Гарантия дана стандартом для всех платформ. На x86 такие операции дешёвые, а на ARM компилятор вставит нужные барьеры.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Ещё по теме «Многопоточность и модель памяти»
- Найти потенциальный дедлок по порядку захвата мьютексов
- Потокобезопасная ленивая инициализация
- compare_exchange
- Ожидание на condition_variable
- Что такое гонка данных
- Как избежать дедлока с двумя мьютексами
- lock_guard, unique_lock, scoped_lock
- Примитив синхронизации и задача