2012-11-20 222 views
10

我不知道是否有可能在同一时间锁定多个互斥锁,如:锁定多个互斥锁

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

    // Code locked by mutex 1. 
} 
Mutex1.Unlock(); 

这将是某些情况下非常有用的。谢谢。

+2

是的,这是可能的。只要小心,没有适当的努力就会很容易导致僵局。 –

回答

12

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

推荐使用范围的锁,(用std::mutexstd::lock_guard例如)解锁设备的异常安全,确保锁总是发布:

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

std::lock_guard<std::mutex> mtx1_lock(mtx1); 
{ 
    std::lock_guard<std::mutex> mtx2_lock(mtx2); 
    { 
    } 
} 

如果你的编译器不支持这些C++ 11层的功能提升在boost::mutexboost::lock_guard中有相似之处。

+0

我使用pthreads,是否有可能保护我的程序免受死锁而不使用c + + 11?我正在使用pthread_mutex_lock并在.Lock()和.Unlock()函数内解锁。 – grimgrom

+0

@grimgrom,是的。提到'lock_guard'是因为它使异常安全性更容易实现,但并不需要避免死锁。为了避免死锁,无论锁定采集之后的代码如何退出,都要始终以相同顺序获取锁并释放_always_。 – hmjd

+0

@grimgrom,注意你可以很容易地为你的'Mutex'类编写你自己的'Lock_guard'类。只需在构造函数中使用'Lock()'和在析构函数中使用'Unlock()'。只要确保'Lock_guard'存储对'Mutex'实例的引用并且不复制它。 – hmjd

26

std::lock似乎是为此目的而存在的。

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

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

2

C++ 17还提供scoped_lock用于锁定多个互斥的特定目的,其防止死锁在RAII风格,类似于lock_guard

#include<mutex> 

std::mutex mtx1, mtx2; 
void foo() 
{ 
    std::scoped_lock lck{mtx1, mtx2}; 
    // proceed 
}