73

C++ で優れたリーダー/ライター ロックを探しています。使用頻度の低い 1 人のライターと頻繁に使用する多数のリーダーのユース ケースがあり、これを最適化したいと考えています。クロスプラットフォームのソリューションが望ましいですが、Windows のみのソリューションも受け入れられます。

4

12 に答える 12

44

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
}

古いコンパイラのバージョンと標準の場合、boostを使用して読み取り/書き込みロックを作成できます。

#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:17.423 に答える
37

boost::threadの新しいバージョンには読み取り/書き込みロックがあります (1.35.0 以降、明らかに以前のバージョンは正しく動作しませんでした)。

それらはshared_lockunique_lock、およびという名前を持ち、upgrade_lockで動作しshared_mutexます。

于 2008-10-28T18:36:58.290 に答える
35

標準の事前にテストされ、事前に構築されたものを使用することは常に良いことです (たとえば、別の回答が示唆する Boost など) が、これは自分で構築するのはそれほど難しくありません。これは、私のプロジェクトから引き出されたばかげた小さな実装です。

#include <pthread.h>

struct rwlock {
    pthread_mutex_t lock;
    pthread_cond_t read, write;
    unsigned readers, writers, read_waiters, write_waiters;
};

void reader_lock(struct rwlock *self) {
    pthread_mutex_lock(&self->lock);
    if (self->writers || self->write_waiters) {
        self->read_waiters++;
        do pthread_cond_wait(&self->read, &self->lock);
        while (self->writers || self->write_waiters);
        self->read_waiters--;
    }
    self->readers++;
    pthread_mutex_unlock(&self->lock);
}

void reader_unlock(struct rwlock *self) {
    pthread_mutex_lock(&self->lock);
    self->readers--;
    if (self->write_waiters)
        pthread_cond_signal(&self->write);
    pthread_mutex_unlock(&self->lock);
}

void writer_lock(struct rwlock *self) {
    pthread_mutex_lock(&self->lock);
    if (self->readers || self->writers) {
        self->write_waiters++;
        do pthread_cond_wait(&self->write, &self->lock);
        while (self->readers || self->writers);
        self->write_waiters--;
    }
    self->writers = 1;
    pthread_mutex_unlock(&self->lock);
}

void writer_unlock(struct rwlock *self) {
    pthread_mutex_lock(&self->lock);
    self->writers = 0;
    if (self->write_waiters)
        pthread_cond_signal(&self->write);
    else if (self->read_waiters)
        pthread_cond_broadcast(&self->read);
    pthread_mutex_unlock(&self->lock);
}

void rwlock_init(struct rwlock *self) {
    self->readers = self->writers = self->read_waiters = self->write_waiters = 0;
    pthread_mutex_init(&self->lock, NULL);
    pthread_cond_init(&self->read, NULL);
    pthread_cond_init(&self->write, NULL);
}

pthreads実際には Windows ネイティブではありませんが、一般的な考え方はここにあります。この実装はライターに少し偏っています (ライターの群れはリーダーを無期限に飢えさせる可能性があります)。writer_unlockバランスを逆にしたい場合は、変更してください。

はい、これは C であり、C++ ではありません。翻訳は読者に委ねられた課題です。

編集

Greg Rogers さんは、POSIX 標準が を指定していると指摘しましたpthread_rwlock_*。を持っていない場合、これは役に立ちませんが、 Pthreads-w32が機能するはずだpthreadsということを思い出しました。このコードを自分で使用するために non- に移植する代わりに、 Windows では Pthreads-w32 を使用し、その他の場所ではネイティブを使用してください。pthreadspthreads

于 2008-10-28T18:46:10.487 に答える
16

競合がない場合、読み取り/書き込みロックは単純なミューテックスよりも 3 倍から 40 倍遅くなる傾向があるため、使用するものは何でも、単純なロックに対して作業負荷のベンチマークを行います。

ここにいくつかの参照があります

于 2008-10-28T19:23:32.380 に答える
10

編集: MSDN マガジンのリンクは利用できなくなりました。CodeProject の記事はhttps://www.codeproject.com/Articles/32685/Testing-reader-writer-locksで入手できるようになり、かなりうまくまとめられています。また、 Compound Synchronization Objectsに関する新しい MSDN リンクも見つけました。

MSDN には、リーダー/ライター ロックに関する記事があり、それらのいくつかの実装が示されています。また、Vista で導入されたカーネル同期プリミティブである Slim リーダー/ライター ロックも導入されています。さまざまな実装の比較に関するCodeProjectの記事もあります (MSDN の記事のものを含む)。

于 2009-01-29T07:29:06.517 に答える
8

C++17 がサポートしていますstd::shared_mutexMSVC++ 2015および 2017でサポートされています。

于 2017-05-28T14:54:56.097 に答える
4

Intel Thread Building Blocks は、いくつかの rw_lock バリアントも提供します。

http://www.threadingbuildingblocks.org/

非常に短い期間の競合用の spin_rw_mutex と、長時間の競合用の queueing_rw_mutex があります。前者は、特にパフォーマンスに敏感なコードで使用できます。後者は、Boost.Thread によって提供されるパフォーマンス、または pthreads を直接使用するパフォーマンスに匹敵します。ただし、プロファイルを作成して、どちらがアクセス パターンに適しているかを確認してください。

于 2008-11-05T19:04:10.117 に答える
3

多数のロック メカニズムを提供し、さまざまなプラットフォームに移植されているACE ライブラリをお勧めします。

問題の境界条件によっては、次のクラスが役立つ場合があります。

  • ACE_RW_Process_Mutex
  • ACE_Write_GuardACE_Read_Guard
  • ACE_Condition
于 2008-10-28T19:08:06.763 に答える
3

Boost.Threadは、リリース 1.35.0 以降、リーダー/ライター ロックを既にサポートしています。これの良いところは、実装が非常にクロスプラットフォームであり、査読済みであり、実際には今後の C++0x 標準のリファレンス実装であることです。

于 2008-10-28T19:10:28.597 に答える
2

Glenn Slayde による Win32 の複数リーダー、単一ライター同期ロック クラス

http://www.glennslayden.com/code/win32/reader-writer-lock

于 2011-05-31T19:31:29.783 に答える
0

Sun の優れたReentrantReadWriteLockをコピーできます。オプションの公平性、ロックのダウングレード、そしてもちろん再入可能などの機能が含まれています。

はい、Java で作成されていますが、Java をまったく知らなくても、簡単に読み取って C++ に変換できます。リンク先のドキュメントには、この実装のすべての動作プロパティが含まれているため、目的の動作を確認できます。

何もなければ、それはガイドです。

于 2008-10-28T18:31:32.483 に答える