web-dev-qa-db-ja.com

複数のミューテックスをロックする

次のように、複数のミューテックスを同時にロックできるかどうか疑問に思っています。

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

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

状況によっては非常に便利です。ありがとう。

15
grimgrom

可能ですが、ロックの順序はアプリケーション全体で一貫している必要があります。そうしないと、デッドロックが発生する可能性があります(2つのスレッドが反対の順序でロックを取得する場合、各スレッドはもう一方のスレッドが一方のロックを解放するのを待機する可能性があります)。

ロックが常に解放されるように、例外安全性のためにスコープ付きロックおよびロック解除機能を使用することをお勧めします( std::lock_guard with std::mutex 例):

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::mutex および boost::lock_guard

11
hmjd

std::lockこの目的のために存在するようです。

デッドロックを回避するために、デッドロック回避アルゴリズムを使用して、指定されたロック可能なオブジェクトlock1、lock2、...、locknをロックします。オブジェクトは、lock、try_lock、unlockの不特定の一連の呼び出しによってロックされます。ロックまたはロック解除の呼び出しで例外が発生した場合、再スローする前に、ロックされたオブジェクトに対してロック解除が呼び出されます。

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

33
Pubby

C++ 17は、scoped_lockと同様に、RAIIスタイルでのデッドロックを防ぐ複数のミューテックスをロックするという特定の目的のためにlock_guardも提供します。

#include<mutex>

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