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