win32の実装についてはコメントしません。これは、はるかに複雑であり、詳細に説明する時間がないためです。そうは言っても、そのインターフェースはpthreadの実装と同じです。つまり、次の答えも同様に有効である必要があります。
v1.51.0以降のboost::shared_mutexのpthread実装の関連部分:
void lock_shared()
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked)
{
shared_cond.wait(lk);
}
++state.shared_count;
}
void lock()
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
exclusive_cond.wait(lk);
}
state.exclusive=true;
}
whileループ条件は、最も関連性の高い部分です。state.exclusive_waiting_blocked
lock_shared関数(ロックの読み取り)の場合、ロックを取得しようとしているスレッド( )またはすでに所有しているスレッド()がある限り、whileループが終了しないことに注意してくださいstate.exclusive
。これは基本的に、書き込みロックが読み取りロックよりも優先されることを意味します。
state.shared_count
ロック機能(書き込みロック)の場合、現在読み取りロック( )を所有しているスレッドまたは別のスレッドが書き込みロック()を所有しているスレッドが少なくとも1つある限り、whileループは終了しませんstate.exclusive
。これにより、基本的に通常の相互排除が保証されます。
デッドロックに関しては、書き込みロックが取得されるとロックが解除されることが保証されている限り、読み取りロックは常に戻ります。書き込みロックに関しては、読み取りロックと書き込みロックが取得されると常にロック解除されることが保証されている限り、戻ることが保証されます。
ご参考までに、state_change
ミューテックスは、これらの関数のいずれかが同時に呼び出されないようにするために使用されます。ロック解除機能はもう少し複雑なので、ここでは説明しません。自由に自分でそれらを見てください、結局あなたはソースを持っています(boost/thread/pthread/shared_mutex.hpp
):)
全体として、これはほとんど教科書の実装であり、幅広いシナリオで広範囲にテストされています(libs/thread/test/test_shared_mutex.cpp
業界全体で大規模に使用されています)。それらを慣用的に使用している限り、あまり心配する必要はありません(再帰的なロックはなく、常にRAIIヘルパーを使用してロックします)。それでも実装を信頼できない場合は、心配しているテストケースをシミュレートするランダム化テストを作成し、数百のスレッドで一晩実行することができます。これは通常、デッドロックを解消するための良い方法です。
では、書き込みロックが要求された後に読み取りロックが取得されるのはなぜですか?使用している診断コードを見ずに言うのは難しいです。印刷ステートメント(または使用しているもの)が完了した後、書き込みスレッドでstate_changeロックが取得される前に、読み取りロックが取得される可能性があります。