锁定多个互斥锁

gri*_*rom 15 c++ multithreading mutex

我想知道是否可以同时锁定多个互斥锁,例如:

 Mutex1.Lock();
 {
     Mutex2.Lock();
     {
          // Code locked by mutex 1 and 2.
     }
     Mutex2.Unlock();

     // Code locked by mutex 1.
 }
 Mutex1.Unlock();
Run Code Online (Sandbox Code Playgroud)

这对某些情况非常有用.谢谢.

Pub*_*bby 32

std::lock 似乎存在于此目的.

使用死锁避免算法锁定给定的Lockable对象lock1,lock2,...,lockn以避免死锁.这些对象被一系列未指定的锁定,try_lock,unlock调用锁定.如果锁定或解锁调用导致异常,则在重新抛出之前会为任何锁定的对象调用unlock.

http://en.cppreference.com/w/cpp/thread/lock


Pas*_* By 13

C++ 17还提供scoped_lock了锁定多个互斥锁的特定目的,这些互斥锁可以防止RAII样式的死锁,类似于lock_guard.

#include<mutex>

std::mutex mtx1, mtx2;
void foo()
{
    std::scoped_lock lck{mtx1, mtx2};
    // proceed
}
Run Code Online (Sandbox Code Playgroud)


hmj*_*mjd 12

这是可能的,但锁定的顺序必须在整个应用程序中保持一致,否则死锁是可能的结果(如果两个线程以相反的顺序获取锁,则每个线程可以在另一个线程上等待以释放其中一个锁).

推荐使用范围的锁定和解锁设备的异常安全,确保锁总是(发布std::lock_guardstd::mutex为例):

std::mutex mtx1;
std::mutex mtx2;

std::lock_guard<std::mutex> mtx1_lock(mtx1);
{
    std::lock_guard<std::mutex> mtx2_lock(mtx2);
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您的编译器不支持这些C++ 11功能,则boost boost::mutexboost::lock_guard.

  • 如果其他地方的代码在 `mtx1` 之前锁定了 `mtx2`,同时这段代码锁定了 `mtx1` 然后是 `mtx2`,那么锁守卫不会拯救你,它会死锁。两个线程将永远等待另一个人释放他们需要的那个。这就是这个答案的开头提到的,但似乎已被 RAII 讨论所掩盖。死锁是多锁的主要问题。 (2认同)
  • 这个例子是不安全的,正如 doug65536 已经提到的,除非你能保证每次这些互斥锁被锁定时,它们总是以相同的顺序被锁定(祝你好运)。绝对安全的方法是使用 std::lock,正如 Pubby 所建议的那样。 (2认同)