Locking multiple mutexes

2019-04-04 10:25发布

问题:

I'm wondering if it's possible to lock multiple mutexes at the same time, like:

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

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

It would be very useful for some situations. Thanks.

回答1:

It is possible but the order of locking must be consistent throughout the application otherwise deadlock is a likely result (if two threads acquire the locks in opposite order then each thread could be waiting on the other to release one of the locks).

Recommend using a scoped lock and unlock facility for exception safety, to ensure locks are always released (std::lock_guard with std::mutex for example):

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

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

If your compiler does not support these C++11 features boost has similar in boost::mutex and boost::lock_guard.



回答2:

std::lock seems to exist for this purpose.

Locks the given Lockable objects lock1, lock2, ..., lockn using a deadlock avoidance algorithm to avoid deadlock. The objects are locked by an unspecified series of calls to lock, try_lock, unlock. If a call to lock or unlock results in an exception, unlock is called for any locked objects before rethrowing.

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



回答3:

C++17 also provides scoped_lock for the specific purpose of locking multiple mutexes that prevents deadlock in a RAII style, similar to lock_guard.

#include<mutex>

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