Как работают std::mutex?

std::mutex является одним из механизмов синхронизации, предоставляемых в языке программирования C++. Он позволяет регулировать доступ нескольких потоков к общим данным, обеспечивая их синхронизацию и избегая возникновения гонок данных.

Операции блокировки и разблокировки в std::mutex выполняются с помощью методов lock() и unlock(). При вызове метода lock() std::mutex блокирует доступ к общим данным, если текущий поток может захватить мьютекс. Если мьютекс уже захвачен другим потоком, текущий поток будет заблокирован до тех пор, пока мьютекс не будет освобожден. Метод unlock() разблокирует мьютекс, позволяя другим потокам получить доступ к общим данным.

Важно использовать мьютексы правильно, чтобы избежать проблем с производительностью и блокировкой потоков. Обычно мьютексы используются вместе с блоками кода, в которых доступ к общим данным должен быть синхронизирован. Например, если несколько потоков пытаются одновременно записать данные в одну переменную, можно использовать мьютекс для блокировки доступа к этой переменной в коде, выполняемом каждым потоком.

Пример использования std::mutex:

#include <iostream>
#include <mutex>
#include <thread>

std::mutex mtx; // создание мьютекса

void printHello(int id) {
    mtx.lock(); // блокировка мьютекса
    std::cout << "Hello from thread " << id << std::endl;
    mtx.unlock(); // разблокировка мьютекса
}

int main() {
    std::thread t1(printHello, 1);
    std::thread t2(printHello, 2);

    t1.join();
    t2.join();

    return 0;
}

В данном примере два потока t1 и t2 выводят сообщение на консоль с использованием std::cout. Поскольку доступ к std::cout не является атомарным, необходимо синхронизировать его использование, чтобы избежать непредсказуемого поведения. Для этого мы используем std::mutex mtx, который блокируется перед каждым вызовом std::cout и разблокируется после него.

Как только один поток захватывает мьютекс с помощью lock(), другой поток может быть заблокирован на этом же мьютексе до его освобождения первым потоком. Это гарантирует, что сообщения будут выводиться последовательно и не перемешиваются.

std::mutex является основным механизмом синхронизации в C++, но также существуют и другие варианты, такие как std::recursive_mutex для рекурсивной блокировки и std::timed_mutex для блокировки с таймером. Выбор правильного механизма синхронизации зависит от конкретных требований вашей программы.