C++ 中的读/写锁

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/244316/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:01:03  来源:igfitidea点击:

Reader/Writer Locks in C++

c++multithreadinglocking

提问by Matt Price

I'm looking for a good reader/writer lock in C++. We have a use case of a single infrequent writer and many frequent readers and would like to optimize for this. Preferable I would like a cross-platform solution, however a Windows only one would be acceptable.

我正在寻找一个好的 C++ 读/写锁。我们有一个用例,有一个不频繁的作者和许多频繁的读者,并希望为此进行优化。最好我想要一个跨平台的解决方案,但是只有一个 Windows 是可以接受的。

采纳答案by Greg Rogers

Newer versions of boost::threadhave read/write locks (1.35.0 and later, apparently the previous versions did not work correctly).

较新版本的boost::thread具有读/写锁(1.35.0 及更高版本,显然以前的版本无法正常工作)。

They have the names shared_lock, unique_lock, and upgrade_lockand operate on a shared_mutex.

它们具有名称shared_lockunique_lock、 和upgrade_lock和 操作于shared_mutex

回答by ephemient

Using standard pre-tested, pre-built stuff is always good (for example, Boost as another answer suggested), but this is something that's not too hard to build yourself. Here's a dumb little implementation pulled out from a project of mine:

使用标准的预先测试、预先构建的东西总是好的(例如,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);
}

pthreadsnot really being Windows-native, but the general idea is here. This implementation is slightly biased towards writers (a horde of writers can starve readers indefinitely); just modify writer_unlockif you'd rather the balance be the other way around.

pthreads并不是真正的 Windows 原生,但总体思路就在这里。这个实现稍微偏向于作家(一群作家可以无限期地让读者饿死);writer_unlock如果您希望平衡相反,只需修改即可。

Yes, this is C and not C++. Translation is an exercise left to the reader.

是的,这是 C 而不是 C++。翻译是留给读者的练习。

Edit

编辑

Greg Rogers pointed out that the POSIX standard does specify pthread_rwlock_*. This doesn't help if you don't have pthreads, but it stirred my mind into remembering: Pthreads-w32should work! Instead of porting this code to non-pthreadsfor your own use, just use Pthreads-w32 on Windows, and native pthreadseverywhere else.

Greg Rogers 指出 POSIX 标准确实指定了pthread_rwlock_*. 如果您没有pthreads,这无济于事,但它让我想起了:Pthreads-w32应该可以工作!不要将此代码移植到非pthreads供您自己使用,只需在 Windows 上使用 Pthreads-w32,pthreads在其他地方使用本机。

回答by Yochai Timmer

Since C++ 17 (VS2015) you can use the standard:

从 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
}

For older compiler versions and standards you can use boostto create a read-write lock:

对于较旧的编译器版本和标准,您可以使用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;

回答by ididak

Whatever you decide to use, benchmark your work load against simple locks, as read/write locks tend to be 3-40x slower than simple mutex, when there is no contention.

无论您决定使用什么,都要针对简单锁对您的工作负载进行基准测试,因为在没有争用的情况下,读/写锁往往比简单互斥锁慢 3-40 倍。

Here is some reference

这里有一些参考

回答by vividos

Edit: The MSDN Magazine link isn't available anymore. The CodeProject article is now available on https://www.codeproject.com/Articles/32685/Testing-reader-writer-locksand sums it up pretty nicely. Also I found a new MSDN link about Compound Synchronisation Objects.

编辑:MSDN 杂志链接不再可用。CodeProject 文章现在可以在https://www.codeproject.com/Articles/32685/Testing-reader-writer-locks 上找到,并且总结得很好。我还发现了一个关于复合同步对象的新 MSDN 链接。

There is an articleabout reader-writer locks on MSDN that presents some implementations of them. It also introduces the Slim reader/writer lock, a kernel synchronisation primitive introduced with Vista. There's also a CodeProject articleabout comparing different implementations (including the MSDN article's ones).

MSDN 上有一篇关于读写锁的文章,介绍了它们的一些实现。它还引入了 Slim 读/写锁,这是 Vista 引入的内核同步原语。还有一篇关于比较不同实现(包括 MSDN 文章)的CodeProject 文章

回答by Serge Rogatch

C++17 supports std::shared_mutex. It is supported in MSVC++ 2015and 2017.

C++17 支持std::shared_mutex. MSVC++ 2015和 2017支持它。

回答by Edward KMETT

Intel Thread Building Blocks also provide a couple of rw_lock variants:

英特尔线程构建块还提供了几个 rw_lock 变体:

http://www.threadingbuildingblocks.org/

http://www.threadingbuildingblocks.org/

They have a spin_rw_mutex for very short periods of contention and a queueing_rw_mutex for longer periods of contention. The former can be used in particularly performance sensitive code. The latter is more comparable in performance to that provided by Boost.Thread or directly using pthreads. But profile to make sure which one is a win for your access patterns.

它们有一个用于极短时间争用的 spin_rw_mutex 和一个用于较长时间争用的 queueing_rw_mutex。前者可用于对性能特别敏感的代码。后者在性能上与 Boost.Thread 或直接使用 pthreads 提供的性能更具可比性。但要确定哪一个是您的访问模式的胜利。

回答by Dong Hoon

I can recommend the ACE library, which provides a multitude of locking mechanisms and is ported to various platforms.

我可以推荐ACE 库,它提供了多种锁定机制并移植到各种平台。

Depending on the boundary conditions of your problem, you may find the following classes useful:

根据问题的边界条件,您可能会发现以下类很有用:

  • ACE_RW_Process_Mutex
  • ACE_Write_Guardand ACE_Read_Guard
  • ACE_Condition
  • ACE_RW_Process_Mutex
  • ACE_Write_GuardACE_Read_Guard
  • ACE_Condition

回答by Dean Michael

Boost.Threadhas since release 1.35.0 already supports reader-writer locks. The good thing about this is that the implementation is greatly cross-platform, peer-reviewed, and is actually a reference implementation for the upcoming C++0x standard.

Boost.Thread从 1.35.0 版本开始就已经支持读写锁了。这样做的好处是该实现是跨平台的、经过同行评审的,实际上是即将推出的 C++0x 标准的参考实现

回答by Vladislav Rastrusny

http://www.codeproject.com/KB/threads/ReaderWriterLock.aspx

http://www.codeproject.com/KB/threads/ReaderWriterLock.aspx

Here is a good and lightweight implementation suitable for most tasks.

这是一个适用于大多数任务的良好且轻量级的实现。