我们发现在代码中有几个地方,并发读取受互斥锁保护的数据相当普遍,而写入却很少。我们的测量似乎表明,使用简单的互斥锁会严重影响代码读取该数据的性能。因此,我们需要的是一个多读/单写互斥锁。我知道这可以建立在更简单的原语之上,但是在尝试这一点之前,我宁愿要求现有的知识:
有什么批准的方法可以从更简单的同步原语中构建多读/单写锁定?
我确实有一个想法,但是我宁愿得到我(可能是错误地)想出的没有偏见的答案。 (注意:我期望的是一种解释方法,可能是伪代码,而不是完整的实现。我当然可以自己编写代码。)
注意事项:
最佳答案
似乎只有互斥量和condition_variable作为同步原语。因此,我在这里写了一个读写器锁,使读者感到饥饿。它使用一个互斥锁,两个conditional_variable和三个整数。
readers - readers in the cv readerQ plus the reading reader
writers - writers in cv writerQ plus the writing writer
active_writers - the writer currently writing. can only be 1 or 0.
它以这种方式使读者感到饥饿。如果有几位作家想写作,那么直到所有作家都完成写作之后,读者才有机会阅读。这是因为以后的读者需要检查
writers
变量。同时,active_writers
变量将保证一次只能有一个写程序可以写。class RWLock {
public:
RWLock()
: shared()
, readerQ(), writerQ()
, active_readers(0), waiting_writers(0), active_writers(0)
{}
void ReadLock() {
std::unique_lock<std::mutex> lk(shared);
while( waiting_writers != 0 )
readerQ.wait(lk);
++active_readers;
lk.unlock();
}
void ReadUnlock() {
std::unique_lock<std::mutex> lk(shared);
--active_readers;
lk.unlock();
writerQ.notify_one();
}
void WriteLock() {
std::unique_lock<std::mutex> lk(shared);
++waiting_writers;
while( active_readers != 0 || active_writers != 0 )
writerQ.wait(lk);
++active_writers;
lk.unlock();
}
void WriteUnlock() {
std::unique_lock<std::mutex> lk(shared);
--waiting_writers;
--active_writers;
if(waiting_writers > 0)
writerQ.notify_one();
else
readerQ.notify_all();
lk.unlock();
}
private:
std::mutex shared;
std::condition_variable readerQ;
std::condition_variable writerQ;
int active_readers;
int waiting_writers;
int active_writers;
};