std::mutex, lock_guard и unique_lock
Защищайте общее состояние с помощью мьютексов и помощников блокировки на основе RAII.
«std::mutex, lock_guard и unique_lock» — бесплатный урок C++ Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.
Зачем нужен мьютекс
Несколько потоков конкурируют за доступ к одним и тем же данным. Мьютекс гарантирует взаимное исключение: одновременно блокировку удерживает только один поток.
Основы std::mutex
Создайте, заблокируйте и разблокируйте. Ручная блокировка подвержена ошибкам — всегда используйте вспомогательные средства RAII.
#include <mutex>
std::mutex mtx;
mtx.lock();
// critical section
mtx.unlock();std::lock_guard: блокировка RAII
Простейшая блокировка RAII. Блокирует мьютекс в конструкторе и разблокирует в деструкторе. Идеально подходит для критических секций, в которых не возникают исключения.
std::mutex mtx;
int counter = 0;
void increment() {
std::lock_guard<std::mutex> lock(mtx);
++counter;
}std::scoped_lock (C++17)
Подобно lock_guard, но может одновременно блокировать несколько мьютексов без взаимной блокировки. В современном коде отдавайте ему предпочтение.
#include <mutex>
std::scoped_lock lock(mtx1, mtx2, mtx3); // locks all atomicallystd::unique_lock: гибкая блокировка
Предоставляет больше возможностей, чем lock_guard:
- Его можно разблокировать и повторно заблокировать в пределах области видимости
- Его можно перемещать (владение можно передать)
- Используется с переменными условия
std::unique_lock<std::mutex> lock(mtx);
lock.unlock(); // release temporarily
// ... do something without the lock ...
lock.lock(); // reacquireКак избежать взаимной блокировки
Два потока могут взаимно заблокировать друг друга, если захватывают блокировки в разном порядке. Захватывайте их в одном общем порядке или используйте std::scoped_lock с несколькими мьютексами.
std::lock для нескольких мьютексов
До C++17 используйте std::lock, чтобы атомарно захватить несколько мьютексов. В C++17 вариант std::scoped_lock стал удобнее.
Рекурсивный мьютекс
std::recursive_mutex позволяет потоку блокировать мьютекс несколько раз. Обычно это указывает на проблемы проектирования — вместо этого переработайте код.
try_lock и timed_mutex
try_lock немедленно возвращает результат, если блокировка занята. std::timed_mutex поддерживает ограниченные по времени попытки блокировки.
Блокировка для чтения и записи
std::shared_mutex (C++17) позволяет одновременно работать множеству читателей или одному эксклюзивному писателю. Используйте его при преобладании операций чтения.
std::shared_mutex sm;
void read() { std::shared_lock lk(sm); /* read */ }
void write() { std::unique_lock lk(sm); /* write */ }Компромисс между степенью детализации
Слишком грубая блокировка снижает параллелизм. Слишком детальная добавляет накладные расходы. Профилируйте и настраивайте программу.
Альтернативы без блокировок
Для сценариев с высокой конкуренцией рассмотрите структуры данных без блокировок (атомарные операции, очереди без блокировок). Их гораздо сложнее правильно реализовать — используйте их только при необходимости и после проверки.
Быстрая проверка
Какую блокировку RAII следует предпочесть при одновременной блокировке нескольких мьютексов?
Итоги
Используйте std::lock_guard для простых критических секций, std::scoped_lock для нескольких мьютексов и std::unique_lock, когда нужна гибкость (переменные условия, ручная разблокировка). Всегда используйте RAII — никогда не вызывайте lock/unlock вручную.
Часто задаваемые вопросы
Урок «std::mutex, lock_guard и unique_lock» бесплатный?
Да — полный текст урока «std::mutex, lock_guard и unique_lock» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.
Чему я научусь в уроке «std::mutex, lock_guard и unique_lock»?
Защищайте общее состояние с помощью мьютексов и помощников блокировки на основе RAII. Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C++ Academy?
Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «std::mutex, lock_guard и unique_lock»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C++ Academy?
Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- std::thread: присоединение и отсоединение
- std::mutex, lock_guard и unique_lock
- Условные переменные и шаблоны рабочих потоков
- Основы std::async и std::future