1

次のコードがある場合:

#include <boost/date_time.hpp>
#include <boost/thread.hpp>

boost::shared_mutex g_sharedMutex;

void reader()
{
    boost::shared_lock<boost::shared_mutex> lock(g_sharedMutex);
    boost::this_thread::sleep(boost::posix_time::seconds(10));
}

void makeReaders()
{
    while (1)
    {
        boost::thread ar(reader);
        boost::this_thread::sleep(boost::posix_time::seconds(3));
    }
}

boost::thread mr(makeReaders);
boost::this_thread::sleep(boost::posix_time::seconds(5));
boost::unique_lock<boost::shared_mutex> lock(g_sharedMutex);

...

常にリーダーが存在するため、一意のロックが取得されることはありません。待機を開始したときに、新しい読み取りロックがミューテックスにアクセスできないようにするunique_lockが必要です(私のwiki検索に基づいて、書き込みバイアスまたは書き込み優先ロックと呼ばれます)。ブーストでこれを行う簡単な方法はありますか? それとも自分で書く必要がありますか?

4

1 に答える 1

2

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_blockedlock_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ロックが取得される前に、読み取りロックが取得される可能性があります。

于 2012-10-11T01:14:40.330 に答える