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

Как писать потокобезопасный код

Вопрос

Как вы избегаете гонок данных и дедлоков в многопоточном C++-коде? Расскажите о средствах и правилах.

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

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

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

Коротко

Главное правило: любые данные, к которым обращаются из нескольких потоков и хотя бы один пишет, должны быть защищены, иначе это гонка данных и UB. Защищаю мьютексом через RAII-замки, lockguard или scopedlock, держу критическую секцию короткой и не вызываю под замком колбэки и ввод-вывод.

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

  • Гонка данных это UB: защищать общие данные мьютексом или атомиками

  • RAII-замки, минимальная критическая секция, никакого чужого кода под замком

  • Единый порядок захвата или scoped_lock для нескольких мьютексов

  • condition_variable только с предикатом

  • Меньше общего состояния: передача сообщений, неизменяемые данные

  • Инструменты: ThreadSanitizer, ревью, стресс-тесты

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

  • Как найти гонку, которая воспроизводится раз в неделю?
  • Когда атомики лучше мьютекса?

Разбор

Главное правило: любые данные, к которым обращаются из нескольких потоков и хотя бы один пишет, должны быть защищены, иначе это гонка данных и UB. Защищаю мьютексом через RAII-замки, lock_guard или scoped_lock, держу критическую секцию короткой и не вызываю под замком колбэки и ввод-вывод. Для одиночных счётчиков и флагов беру std::atomic. Против дедлоков: единый порядок захвата мьютексов во всём коде, а если нужно несколько сразу, std::scoped_lock(a, b). Ожидание события делаю через condition_variable::wait с предикатом, а условие меняю под тем же мьютексом. Ещё лучше сокращать общее состояние: очереди сообщений, неизменяемые данные, разделение работы по потокам. Для проверки гоняю тесты под ThreadSanitizer (-fsanitize=thread), он ловит гонки, которые редко проявляются, и делаю стресс-тесты с большим числом потоков.

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

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