2016-07-20 6 views
5

私は、2つのboost :: scoped_locksを同時に保持すると問題があるかどうかを知りたいと思います。ロックは異なるmutexをロックしています。次の例を考えてみましょう。同時に2つのミューテックスロックを保持する

void foo1() 
{ 
    boost::recursive_mutex::scoped_lock lock(mutex1); 
    foo2(); 
} 

void foo2() 
{ 
    boost::recursive_mutex::scoped_lock lock(mutex2); 
} 

これはデッドロックを引き起こすものではないことがわかります。しかし、他の問題はありますか?スレッドが長時間スリープする可能性がありますか?

答えて

5

複数のロックを保持することは、そのものではありません。問題です。

他のスレッドが同じロックを別の順序で取得しようとしたときに、デッドロックがABBAになると問題が発生します。スレッド1のロックABの場合、スレッド2はBをロックしたいとし、Aを終了し、両端がブロックされるようにします(ロックインターリーブするとt1はAをロックし、次にt2はBをロックしてから他方をロックしようとします)続けることができるようにロックのうちの1つを解放する(そして、自分の保持しているロックを解放して、他のロックを続けることができるようにする)。

したがって、一般的な経験則は次のとおりです。複数のロックを取得する必要がある場合は、すべてのスレッドが常にが同じ順序でそれらのロックを取得しようとしていることを確認してください。

+0

ありがとうございました! :) –

+0

ロックの順序を保証する1つの方法は、mutexes/locksの周りに軽量のラッパーを置き、レイヤーiのコンストラクターがレイヤー(i-1)の取得したロックのconst refを取るようにすることです。そうすれば、他の方法で構築することはできません。または、C++ 17を使用して同時にロックします。 – lorro

+0

@lorro私はこの問題に対処する方法がたくさんあることをよく承知しています。しかし、私は問題の実装を解決する方法をアドバイスするつもりではなく、潜在的な問題とは何かを指摘することとそれを回避する一般的なルールを指摘することでした。実装は読者のための練習として残しました。 :-) –

5

このの場合、逆の順序で両方のミューテックスを取得するとデッドロックが発生します。次のようにインターリーブ

void bar1() { 
    boost::recursive_mutex::scoped_lock lock(mutex2); 
    bar2(); 
} 

void bar2() { 
    boost::recursive_mutex::scoped_lock lock(mutex1); 
} 

2つのスレッドがデッドロックします:

        mutex1 mutex2 
Time Thread A  Thread B owner owner 
    0  foo1()      A 
    1     bar1()  A  B 
    2     bar2()  A  B 
    3  foo2()      A  B 

この時点で& Bがデッドロックしているスレッド。私はboostがそれに対して保護を提供しているとは思わない。

+0

ありがとうございました! :) –

関連する問題