← Назад ко всем вопросам

Для чего нужен Mutex

1️⃣ Как кратко ответить

Mutex (мьютекс) используется для обеспечения синхронизации потоков в многопоточных приложениях. Он предотвращает одновременный доступ нескольких потоков к общим ресурсам, таким как переменные или структуры данных, обеспечивая тем самым целостность данных и предотвращая состояния гонки.

2️⃣ Подробное объяснение темы

В многопоточных приложениях несколько потоков могут одновременно пытаться получить доступ к общим ресурсам, таким как переменные, структуры данных или файлы. Если доступ к этим ресурсам не контролируется, это может привести к состояниям гонки, когда результат программы зависит от порядка выполнения потоков. Это может вызвать непредсказуемое поведение программы и ошибки.

Mutex (сокращение от "mutual exclusion" — взаимное исключение) — это механизм синхронизации, который позволяет только одному потоку в данный момент времени получить доступ к ресурсу. Когда поток захватывает мьютекс, другие потоки, пытающиеся захватить тот же мьютекс, блокируются до тех пор, пока первый поток не освободит его.

Пример использования мьютекса в C++

#include <iostream>
#include <thread>
#include <mutex>
​
// Создаем глобальный мьютекс
std::mutex mtx;
​
// Общий ресурс, к которому будут обращаться потоки
int sharedCounter = 0;
​
// Функция, которая будет выполняться в потоках
void incrementCounter() {
    for (int i = 0; i < 1000; ++i) {
        // Захватываем мьютекс перед доступом к общему ресурсу
        mtx.lock();
        // Увеличиваем общий счетчик
        ++sharedCounter;
        // Освобождаем мьютекс после завершения работы с ресурсом
        mtx.unlock();
    }
}
​
int main() {
    // Создаем два потока, которые будут выполнять функцию incrementCounter
    std::thread t1(incrementCounter);
    std::thread t2(incrementCounter);
​
    // Ожидаем завершения потоков
    t1.join();
    t2.join();
​
    // Выводим значение общего счетчика
    std::cout << "Final counter value: " << sharedCounter << std::endl;
​
    return 0;
}

Объяснение кода:

  • std::mutex mtx;: Создаем объект мьютекса, который будет использоваться для синхронизации доступа к общему ресурсу sharedCounter.

  • int sharedCounter = 0;: Инициализируем общий счетчик, который будет увеличиваться потоками.

  • void incrementCounter(): Функция, которая будет выполняться в каждом потоке. Она увеличивает значение sharedCounter 1000 раз.

  • mtx.lock();: Захватываем мьютекс перед тем, как получить доступ к sharedCounter. Это гарантирует, что только один поток может изменить значение sharedCounter в данный момент времени.

  • ++sharedCounter;: Увеличиваем значение общего счетчика.

  • mtx.unlock();: Освобождаем мьютекс после завершения работы с sharedCounter, позволяя другим потокам захватить мьютекс и получить доступ к ресурсу.

  • std::thread t1(incrementCounter); std::thread t2(incrementCounter);: Создаем два потока, которые выполняют функцию incrementCounter.

  • t1.join(); t2.join();: Ожидаем завершения обоих потоков, чтобы убедиться, что все инкременты выполнены до вывода результата.

  • std::cout << "Final counter value: " << sharedCounter << std::endl;: Выводим итоговое значение счетчика. Благодаря использованию мьютекса, итоговое значение будет равно 2000, так как оба потока корректно увеличили счетчик по 1000 раз каждый.

Использование мьютекса позволяет избежать состояния гонки и гарантирует, что общий ресурс будет изменяться корректно, даже если к нему обращаются несколько потоков одновременно.

Тема: Многопоточность / Синхронизация
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки