这是情况
boost::shared_mutex rwlock;
void test()
{
boost::unique_lock < boost::shared_mutex > writelock(rwlock);
// here we have deadlock
}
int main()
{
boost::shared_lock < boost::shared_mutex > readlock(rwlock);
test();
}
我知道我们可以这样做:
{
boost::upgrade_lock<boost::shared_mutex> upgradeable_lock(rwlock); // here we obtain readlock
{
boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(upgradeable_lock); // right now we upgrade readlock to writelock
}
}
但是如果在我的第一个例子中我们有另一个范围,我们看不到upgradeable_lock。如何解决这个问题?
答案 0 :(得分:1)
我认为真正的代码要困难得多,在调用堆栈中多次获取读锁定,然后你需要在某处写入,从未预料到。
我在这里猜测一下,但如果这是真的,并且你不想改变它,那么你必须从你的写作功能走上呼叫路径,并且总是释放在您进行相关调用之前进行shared_lock,然后再次获取它。
读/写锁是很好的,但它们往往会误导开发人员使用读锁通胀。
只要你可以重构,尝试将读锁减少到那些你必须阅读的地方。保持关键部分尽可能短,并避免内部的函数调用,也可能获得该锁定。
当你完成这项工作后,对现在必须写的函数的更改将不再是一个大问题。顺便说一句,这也将改善并发性,因为作家将有更多的机会找到片刻,没有读者持有读锁定。你现在可能更喜欢那种重构,因为它会让生活变得更容易。
另一个猜测:如果您在较长的过程中使用这些读锁来获得稳定的数据状态,您可能现在想重新考虑该选择。你真正想要的是某种软件事务记忆。