我有一组数据结构,我需要用读/写锁来保护.我知道boost :: shared_lock,但我想使用std :: mutex,std :: condition_variable和/或std :: atomic进行自定义实现,这样我就能更好地理解它是如何工作的(稍后再调整) .
每个数据结构(可移动但不可复制)将从一个名为Commons的类继承,该类封装了锁定.我希望公共接口看起来像这样:
class Commons {
public:
void read_lock();
bool try_read_lock();
void read_unlock();
void write_lock();
bool try_write_lock();
void write_unlock();
};
Run Code Online (Sandbox Code Playgroud)
...以便某些人可以公开继承:
class DataStructure : public Commons {};
Run Code Online (Sandbox Code Playgroud)
我正在编写科学代码,通常可以避免数据争用; 这种锁定主要是为了防止我以后可能犯的错误.因此,我的优先级是低读取开销,所以我不会妨碍正确运行的程序太多.每个线程可能都在自己的CPU核心上运行.
你能告诉我(伪代码是好的)读者/作家锁吗?我现在所拥有的应该是防止作家饥饿的变种.到目前为止,我的主要问题是read_lock在检查读取是否可以安全地实际递增读取器计数之间的差距,之后write_lock知道等待.
void Commons::write_lock() {
write_mutex.lock();
reading_mode.store(false);
while(readers.load() > 0) {}
}
void Commons::try_read_lock() {
if(reading_mode.load()) {
//if another thread calls write_lock here, bad things can happen
++readers;
return true;
} else return false;
}
Run Code Online (Sandbox Code Playgroud)
我对多线程有点新意,我真的很想理解它.在此先感谢您的帮助!
我想使用新的标准线程而不是boost:threads但我注意到旧的shared_mutex不可用.什么是一个很好的建议来取代这个功能,并给我一个多读者,单作家锁?
任何解释每个的实时场景都将受到赞赏.除了pthreads之外还有其他方法来处理同步.互斥体与递归互斥体(任何实时场景)有何不同?
我不确定我的术语是否正确但是这里有 - 我有这个函数,多个线程用来写数据(在注释中使用伪代码来说明我想要的)
//these are initiated in the constructor
int* data;
std::atomic<size_t> size;
void write(int value) {
//wait here while "read_lock"
//set "write_lock" to "write_lock" + 1
auto slot = size.fetch_add(1, std::memory_order_acquire);
data[slot] = value;
//set "write_lock" to "write_lock" - 1
}
Run Code Online (Sandbox Code Playgroud)
写入的顺序并不重要,我需要的是每次写入都要转到一个唯一的插槽
虽然每隔一段时间,我需要一个线程来使用此函数读取数据
int* read() {
//set "read_lock" to true
//wait here while "write_lock"
int* ret = data;
data = new int[capacity];
size = 0;
//set "read_lock" to false
return ret;
}
Run Code Online (Sandbox Code Playgroud)
所以它基本上交换了缓冲区并返回旧缓冲区(我删除了容量逻辑以使代码片段更短)
从理论上讲,这应该导致2种操作场景:
1 - 只是一堆写入容器的线程
2 - …
我想实现在C多线程LRU缓存++使用此文章的提示或灵感。它适用于 Go,但所需的概念或多或少也存在于 C++ 中。本文建议在散列表和链表周围使用带有共享互斥锁的细粒度锁定。
因此,我打算使用 编写缓存std::unordered_map
,std::list
并使用std::shared_timed_mutex
. 我的用例包括几个线程 (4-8) 使用此缓存作为拼写错误的单词和相应可能的更正的存储。缓存的大小约为 10000-100000 个项目。
但是我在几个地方读到,使用共享互斥锁而不是普通互斥锁几乎没有意义,而且速度更慢,尽管我找不到一些带有数字的真实基准或至少在何时使用和何时不使用的模糊指南共享互斥锁。而其他来源建议在您有并发读取器或多或少超过并发写入器时使用共享互斥锁。
std::shared_timed_mutex
比使用一个普通的更好std::mutex
?读者/阅读人数应该多于作者/写作人数多少次?我当然知道这取决于很多因素,但是我应该如何决定使用哪个?std::shared_mutex
(从C ++ 17)做比较,定时一个在性能上有什么区别?PS我觉得会有“首先测量/描述最适合你的情况”。我会,但我需要先实现一个,如果有一些启发式可供选择,而不是同时实现选项和测量,那就太好了。此外,即使我进行测量,我认为结果也将取决于我使用的数据。并且很难预测真实数据(例如对于云中的服务器)。
我的理解是:std::mutex
阻止其他线程,无论他们是否想要读取或写入,而boost::shared_mutex
允许多次读取.
所以我的问题是,我是否应该总是选择boost::shared_mutex
而不是正常std::mutex
来允许并行读取的可能性?使用正常std::mutex
感觉就像我否认一些可能的读取吞吐量....?
我试图使用shared_mutex在C++中使用读/写锁
typedef boost::shared_mutex Lock;
typedef boost::unique_lock< Lock > WriteLock;
typedef boost::shared_lock< Lock > ReadLock;
class Test {
Lock lock;
WriteLock writeLock;
ReadLock readLock;
Test() : writeLock(lock), readLock(lock) {}
readFn1() {
readLock.lock();
/*
Some Code
*/
readLock.unlock();
}
readFn2() {
readLock.lock();
/*
Some Code
*/
readLock.unlock();
}
writeFn1() {
writeLock.lock();
/*
Some Code
*/
writeLock.unlock();
}
writeFn2() {
writeLock.lock();
/*
Some Code
*/
writeLock.unlock();
}
}
Run Code Online (Sandbox Code Playgroud)
代码似乎工作正常,但我有一些概念性的问题.
Q1.我已经看到了在http://en.cppreference.com/w/cpp/thread/shared_mutex/lock上使用unique_lock和shared_lock的建议,但我不明白为什么因为shared_mutex已经支持lock和lock_shared方法了?
Q2.这段代码是否有可能导致写入饥饿?如果是,那么我怎样才能避免饥饿呢?
Q3.有没有其他锁定类我可以尝试实现读写锁?