Какой механизм может атомарно заблокировать два мьютекса
1️⃣ Как кратко ответить
Для атомарной блокировки двух мьютексов в C++ используется функция std::lock. Она гарантирует, что оба мьютекса будут заблокированы без взаимоблокировки (deadlock).
2️⃣ Подробное объяснение темы
В многопоточных приложениях часто возникает необходимость синхронизации доступа к общим ресурсам. Мьютексы (mutexes) — это один из основных инструментов для управления доступом к таким ресурсам. Однако, когда требуется заблокировать более одного мьютекса одновременно, существует риск взаимоблокировки (deadlock), если блокировки выполняются в неправильном порядке.
Функция std::lock из стандартной библиотеки C++ решает эту проблему, предоставляя механизм для атомарной блокировки нескольких мьютексов. Она принимает произвольное количество мьютексов и блокирует их все одновременно, гарантируя, что не произойдет взаимоблокировки.
Пример использования std::lock:
#include <iostream>
#include <thread>
#include <mutex>
// Два мьютекса для синхронизации доступа к ресурсам
std::mutex mutex1;
std::mutex mutex2;
// Функция, которая будет выполняться в потоке
void threadFunction(int id) {
// Атомарная блокировка двух мьютексов
std::lock(mutex1, mutex2);
// Использование std::lock_guard для автоматического освобождения мьютексов
std::lock_guard<std::mutex> lock1(mutex1, std::adopt_lock);
std::lock_guard<std::mutex> lock2(mutex2, std::adopt_lock);
// Критическая секция, где доступ к ресурсам защищен
std::cout << "Thread " << id << " has locked both mutexes." << std::endl;
// Мьютексы будут автоматически освобождены при выходе из области видимости
}
int main() {
// Создание двух потоков, которые будут выполнять функцию threadFunction
std::thread t1(threadFunction, 1);
std::thread t2(threadFunction, 2);
// Ожидание завершения потоков
t1.join();
t2.join();
return 0;
}
Разбор кода:
-
std::mutex mutex1;иstd::mutex mutex2;: Объявление двух мьютексов, которые будут использоваться для синхронизации доступа к ресурсам. -
void threadFunction(int id): Функция, которая будет выполняться в каждом потоке. Она принимает идентификатор потока для вывода информации. -
std::lock(mutex1, mutex2);: Атомарная блокировка обоих мьютексов. Эта функция гарантирует, что оба мьютекса будут заблокированы без риска взаимоблокировки. -
std::lock_guard<std::mutex> lock1(mutex1, std::adopt_lock);иstd::lock_guard<std::mutex> lock2(mutex2, std::adopt_lock);: Использованиеstd::lock_guardсstd::adopt_lockдля управления временем жизни мьютексов.std::adopt_lockуказывает, что мьютексы уже заблокированы и их не нужно блокировать снова. -
std::cout << "Thread " << id << " has locked both mutexes." << std::endl;: Критическая секция, где выполняется работа с защищенными ресурсами. -
t1.join();иt2.join();: Ожидание завершения потоков, чтобы программа не завершилась до их окончания.
Использование std::lock позволяет избежать сложностей, связанных с ручным управлением порядком блокировки мьютексов, и минимизирует риск взаимоблокировок в многопоточных приложениях.
🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!
Подписаться