2012-11-20 9 views
10

それは同時に複数のミューテックスをロックすることが可能だ場合、私は同じように、思ったんだけど:ロック複数のミューテックス

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

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

それはいくつかの状況のた​​めに非常に有用であろう。ありがとう。

+2

はい、可能です。ちょうど慎重に、適切な勤勉をせずに行うと、簡単にデッドロックにつながる可能性があります。 –

答えて

12

デッドロックが発生する可能性があります(2つのスレッドが逆の順序でロックを取得した場合、各スレッドがロックの1つを解放するのを待っている可能性があります) 。

常に解放されている(例えば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'は、例外安全性を達成するのがはるかに簡単になるので言及されていますが、デッドロックを回避する必要はありません。デッドロックを回避するには、ロック獲得に続くコードがどのように終了するかにかかわらず、ロックが常に同じ順序で取得され、_常にロードされるようにします。 – hmjd

+0

@grimgrom、あなたの 'Mutex'クラスのためのあなた自身の' Lock_guard'クラスを簡単に書くことができます。コンストラクタでは 'Lock()'、デストラクタでは 'Unlock()'だけです。 'Lock_guard'が' Mutex'インスタンスへの参照を格納し、それをコピーしないことを確かめてください。 – hmjd

26

std::lockがこのように存在するようです。

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

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

2

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

#include<mutex> 

std::mutex mtx1, mtx2; 
void foo() 
{ 
    std::scoped_lock lck{mtx1, mtx2}; 
    // proceed 
} 
関連する問題