118

一部のデータを頻繁に読み取る必要があるマルチスレッド アプリがあり、そのデータが時々更新されます。現在、ミューテックスはそのデータへのアクセスを安全に保ちますが、複数のスレッドが同時に読み取れるようにし、更新が必要な場合にのみロックアウトできるようにするため、高価です (更新スレッドは他のスレッドが終了するのを待つことができます)。 .

これが本来あるべきことだと思いますがboost::shared_mutex、使い方がよくわからず、明確な例も見つかりませんでした。

始めるために使用できる簡単な例はありますか?

4

6 に答える 6

174

1800 情報はほぼ正しいですが、修正したい問題がいくつかあります。

boost::shared_mutex _access;
void reader()
{
  boost::shared_lock< boost::shared_mutex > lock(_access);
  // do work here, without anyone having exclusive access
}

void conditional_writer()
{
  boost::upgrade_lock< boost::shared_mutex > lock(_access);
  // do work here, without anyone having exclusive access

  if (something) {
    boost::upgrade_to_unique_lock< boost::shared_mutex > uniqueLock(lock);
    // do work here, but now you have exclusive access
  }

  // do more work here, without anyone having exclusive access
}

void unconditional_writer()
{
  boost::unique_lock< boost::shared_mutex > lock(_access);
  // do work here, with exclusive access
}

また、shared_lock とは異なり、一度に 1 つのスレッドしか upgrade_lock を取得できないことにも注意してください。したがって、すべてのリーダーが条件付きライターである場合は、別の解決策を見つける必要があります。

于 2011-01-27T18:45:28.377 に答える
49

C ++ 17(VS2015)以降、読み取り/書き込みロックの標準を使用できます。

#include <shared_mutex>

typedef std::shared_mutex Lock;
typedef std::unique_lock< Lock > WriteLock;
typedef std::shared_lock< Lock > ReadLock;

Lock myLock;


void ReadFunction()
{
    ReadLock r_lock(myLock);
    //Do reader stuff
}

void WriteFunction()
{
     WriteLock w_lock(myLock);
     //Do writer stuff
}

古いバージョンの場合、同じ構文でブーストを使用できます。

#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>

typedef boost::shared_mutex Lock;
typedef boost::unique_lock< Lock >  WriteLock;
typedef boost::shared_lock< Lock >  ReadLock;
于 2011-06-23T07:15:07.580 に答える
18

経験的な情報を追加するために、アップグレード可能なロックの全体の問題を調査してきましたアップグレードされていなくても、1 つのスレッドだけが upgrade_lock を持つことができるという重要な情報を追加するのは良い答えです。これは、最初に共有ロックを解放しないと、共有ロックから一意のロックにアップグレードできないことを意味するため重要です。(これは他の場所で議論されていますが、最も興味深いスレッドはここにありますhttp://thread.gmane.org/gmane.comp.lib.boost.devel/214394 )

ただし、ロックへのアップグレードを待機しているスレッド (つまり、すべてのリーダーが共有ロックを解放するのを待つ必要がある) と、同じこと (つまり、unique_lock) を待機しているライター ロックとの間に重要な (文書化されていない) 違いがあることを発見しました。

  1. shared_mutex で unique_lock を待っているスレッドは、入ってくる新しいリーダーをブロックし、ライターの要求を待たなければなりません。これにより、リーダーがライターを飢えさせることはありません (ただし、ライターがリーダーを飢えさせる可能性はあると思います)。

  2. upgradeable_lock がアップグレードされるのを待っているスレッドは、他のスレッドが共有ロックを取得できるようにするため、リーダーが非常に頻繁に使用される場合、このスレッドは枯渇する可能性があります。

これは考慮すべき重要な問題であり、おそらく文書化する必要があります。

于 2011-03-14T22:01:57.870 に答える
2

リーダーの数と同じ数のセマフォを使用します。各リーダーが読み取るためにセマフォを 1 カウント取得するようにします。これにより、すべてのリーダーが同時に読み取ることができます。次に、書き込み前にすべてのセマフォ カウントをライターに取得させます。これにより、ライターはすべての読み取りが完了するまで待機し、書き込み中に読み取りをブロックします。

于 2010-11-20T07:31:44.853 に答える