Блокировка нескольких мьютексов
Мне интересно, можно ли одновременно блокировать несколько мьютексов, например:
Mutex1.Lock();
{
Mutex2.Lock();
{
// Code locked by mutex 1 and 2.
}
Mutex2.Unlock();
// Code locked by mutex 1.
}
Mutex1.Unlock();
Это было бы очень полезно для некоторых ситуаций. Спасибо.
Ответы
Ответ 1
Возможно, но порядок блокировки должен быть согласованным во всем приложении, в противном случае тупик является вероятным результатом (если два потока получают блокировки в противоположном порядке, то каждый поток может ждать на другом, чтобы освободить один из замков).
Порекомендуйте использовать блокировку с блокировкой и разблокировкой для обеспечения безопасности исключений, чтобы гарантировать, что блокировки всегда отпускаются (std::lock_guard
с std::mutex
, например):
std::mutex mtx1;
std::mutex mtx2;
std::lock_guard<std::mutex> mtx1_lock(mtx1);
{
std::lock_guard<std::mutex> mtx2_lock(mtx2);
{
}
}
Если ваш компилятор не поддерживает эти возможности С++ 11, то boost имеет схожесть в boost::mutex
и boost::lock_guard
.
Ответ 2
std::lock
, похоже, существует для этой цели.
Заблокирует данные Locklock objects lock1, lock2,..., lockn, используя алгоритм избежания тупиковой ситуации, чтобы избежать тупиковой ситуации. Объекты блокируются неуказанной серией вызовов блокировки, try_lock, разблокировки. Если вызов блокировки или разблокировки приводит к исключению, разблокировка вызывается для любых заблокированных объектов перед повторным запуском.
http://en.cppreference.com/w/cpp/thread/lock
Ответ 3
С++ 17 также предоставляет scoped_lock
для конкретной цели блокировки нескольких мьютексов, которые предотвращают взаимоблокировку в стиле RAII, аналогично lock_guard
.
#include<mutex>
std::mutex mtx1, mtx2;
void foo()
{
std::scoped_lock lck{mtx1, mtx2};
// proceed
}