读者/作者用C ++锁定

时间:2008-10-28 18:26:51

标签: c++ multithreading locking

我正在寻找一个很好的C ++读写器锁。我们有一个不常见的作家和许多常见读者的用例,并希望为此进行优化。我更喜欢跨平台的解决方案,但只有Windows可以接受。

12 个答案:

答案 0 :(得分:33)

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

他们的名称为shared_lockunique_lockupgrade_lock,并在shared_mutex上运作。

答案 1 :(得分:33)

使用标准预测试,预先构建的东西总是很好(例如,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,如果您宁愿相反,那么就可以修改pthread_rwlock_*

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

修改

Greg Rogers指出POSIX标准确实指定了pthreads。如果你没有pthreads,这没有任何帮助,但它激起了我的记忆:Pthreads-w32应该有效!不要将此代码移植到非pthreads供自己使用,而只需在Windows上使用Pthreads-w32,在其他地方使用本地{{1}}。

答案 2 :(得分:20)

您可以使用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;

Lock myLock;


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

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

答案 3 :(得分:13)

无论您决定使用什么,都要将工作负载与简单锁定进行对比,因为当没有争用时,读/写锁定比简单互斥锁慢3-40倍。

这是some reference

答案 4 :(得分:9)

编辑:MSDN Magazine链接不再可用。 CodeProject的文章现在可以在https://www.codeproject.com/Articles/32685/Testing-reader-writer-locks上找到,并且很好地总结了它。我还找到了关于Compound Synchronisation Objects的新MSDN链接。

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

答案 5 :(得分:4)

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

http://www.threadingbuildingblocks.org/

他们有一个spin_rw_mutex用于非常短的争用时间,而一个queueing_rw_mutex用于更长时间的争用。前者可用于特别敏感的性能代码。后者在性能上与Boost.Thread或直接使用pthreads提供的性能相当。但是要确定哪一个是您的访问模式的胜利。

答案 6 :(得分:4)

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

答案 7 :(得分:3)

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

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

  • ACE_RW_Process_Mutex
  • ACE_Write_GuardACE_Read_Guard
  • ACE_Condition

答案 8 :(得分:3)

Boost.Thread自发布以来1.35.0已经支持读写器锁。关于这一点的好处是,实施是跨平台的,经过同行评审的,实际上是a reference implementation for the upcoming C++0x standard

答案 9 :(得分:2)

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

这是一个适合大多数任务的优秀且轻量级的实现。

答案 10 :(得分:2)

Glenn Slayde的Win32多读取器,单写器同步锁定类

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

答案 11 :(得分:0)

你可以复制Sun的优秀ReentrantReadWriteLock。它包括可选的公平性,锁定降级,当然还有可重入性等功能。

是的,它是用Java编写的,但即使你不懂任何Java,也可以轻松地将它读取并转换为C ++。我链接到的文档包含此实现的所有行为属性,因此您可以确保它执行您想要的操作。

如果不出意外,这是一个指南。