0Pricing
C++ Academy · Урок

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 atomically

std::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 — локальная установка не требуется.

Все уроки этого курса

  1. std::thread: присоединение и отсоединение
  2. std::mutex, lock_guard и unique_lock
  3. Условные переменные и шаблоны рабочих потоков
  4. Основы std::async и std::future
← Назад к C++ Academy