我正在尝试使用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();
}
}
该代码似乎工作正常,但我有一些概念性问题。
Q1。我已经看到了在http://en.cppreference.com/w/cpp/thread/shared_mutex/lock上使用unique_lock和shared_lock的建议,但是我不明白为什么这样,因为shared_mutex已经支持lock和lock_shared方法了?
Q2。此代码是否有可能导致写饥饿?如果是,那我该如何避免饥饿呢?
Q3。我可以尝试实现读写锁定的任何其他锁定类吗?
最佳答案
Q1:使用互斥包装
建议使用包装器对象而不是直接管理互斥锁,以避免不幸的情况,在这种情况下,您的代码被中断并且互斥锁未释放,从而使其永远处于锁定状态。
这是RAII的原理。
但这仅在您的ReadLock或WriteLock在使用它的函数本地时才有效。
例子:
readFn1() {
boost::unique_lock< Lock > rl(lock);
/*
Some Code
==> imagine exception is thrown
*/
rl.unlock(); // this is never reached if exception thrown
} // fortunately local object are destroyed automatically in case
// an excpetion makes you leave the function prematurely
在您的代码中,如果函数之一被中断,则将无法正常工作,因为您的ReadLock WriteLock对象是Test的成员,而不是局部于设置锁的函数。
Q2:写饥饿
尚不清楚您将如何调用读者和作家,但是是的,存在风险:
如果要避免饥饿,则必须确保等待写入的编写者确实有机会设置其unique_lock。例如,在您的读者中输入一些代码来检查作家是否在设置锁之前正在等待。
Q3其他锁定类
不太确定您要寻找的内容,但我觉得
condition_variable
可能会让您感兴趣。但是逻辑有些不同。也许,您还可以通过开箱即用的思维找到解决方案:也许有一个合适的无锁数据结构,可以通过稍微改变方法来促进读者和作家的共存?