【发布时间】:2020-04-29 19:36:13
【问题描述】:
我正在更新以前使用自己的读写锁机制的代码(此代码是在 C++11 之前编写的,并且 std::shared_mutex 尚不存在) 使用标准版本的 C++。
有两个类叫做ReadLock和WriteLock,ReadLock可以通过方法调用升级为WriteLock。 WriteLock 也可以随时获取,无需从 shared_lock 升级。 阅读 shared_lock 的 C++ 标准版本,我认为它简单明了。
ReadLock 将被 shared_lock 替换 WriteLock 将替换为 unique_lock 并且可以在任何时候调用 lock() 来触发以获取 Writelock 升级到 Writelock 只需两步 解锁 shared_lock 和锁定 unique_lock
我现在的问题是,当我通过讨论阅读时,可能存在特定问题,并且像这样的线程引起了关注(来自 Howard Hinnant 的线程) Can a shared lock on a std::shared_timed_mutex be upgraded to an exclusive lock?
所以我考虑改用 boost 版本,因为它支持 upgrade_lock 和 boost::upgrade_to_unique_lock,但我对如何处理它的设计感到困惑。
WriteLock 类既可以表示 unique_lock 和/或 upgrade_lock 和 upgrade_to_unique_lock 对象,因为如上所述,WriteLock 也可以在没有 shared_lock 的情况下实现。
另外,如果我使用 boost 中的 upgrade_lock,我对如何显式触发 lock() 和 unlock() 机制感到困惑; boost::upgrade_lock 有一个构造函数,它接受 defer_lock 作为参数,并具有我可以随时使用的 lock() 和 unlock() 方法,但是如果我们使用 boost::upgrade_to_unique_lock() 将其升级为唯一锁,我看不到相同的功能,创建 upgrade_to_unique_lock() 的对象会自动转换并锁定它。
这是我想要达到的伪代码 方法一基本操作
void foo()
{
ReadLock readLock = someWrapper->AcquireReader(); // return a shared lock
...
WriteLock writeLock = readLock->UpgradeToWriter(); // returns a unique lock
writeLock->Lock();
// do something here
} // writelock are unlock since constructor is called
方法 2 直接写锁
void foo()
{
WriteLock writeLock = someWrapper->GetWriter(); // acquire lock straight
writeLock->Lock();
// do something here
} // writelock are unlock since constructor is called
}
所以我的问题是
- 如果我使用 std C++ 是否有效,我需要使用 boost 来代替,或者 C++ std::shared_mutex 是否足够? 在上面的示例中,UpgradeToWriter() 和 GetWriter() 都只会返回一个带有 unique_lock 的对象,但 Upgrade 只会首先解锁 shared_lock。
- 如果我使用 boost 版本,我应该如何处理设计,因为 upgrade_to_unique_lock 与 unique_lock 的类型不同? 我在想 WriteLock 类都包含 unique_lock、upgrade_lock 和 boost:upgrade_to_unique_lock 的定义,并且无论是升级还是简单的获取都会被锁定,这让我想到了我的最后一个也是最后一个问题
- 如何显式或延迟/触发 boost:upgrade_to_unique_lock 的锁定?因为它没有 defer_lock 参数,也没有 lock() 和 unlock() 方法,只有构造函数来做他的事情?
来自 boost::upgrade_to_unique_lock 用法的 boost 示例,所有示例都类似于以下代码,自动创建对象会触发转换和锁定。
void writer()
{
// get upgradable access
boost::upgrade_lock<boost::shared_mutex> lock(_access);
// get exclusive access
boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock); // <-- want this to be performed or triggered explicitly, how?
// now we have exclusive access
}
先谢谢你了,我知道这里有C++高手可以帮助兄弟们
【问题讨论】:
-
如果两个读卡器同时尝试升级他们的锁,你想发生什么?或者你想要一个特殊的“不可分级锁”,一次只能有一个读者拥有?
-
Sane 库升级有 3 个锁:读、升级和写。最多可以存在一个(上/写)。一个 up 可以存在任意数量的读取。升级到写入会阻塞所有新的读取器并等待现有读取器完成,然后变成写入锁。 OP手写的系统似乎没有这样做?看来 boost 确实如此。这是你的问题吗,OP?
-
@DavidSchwartz writer lock 应该是独占的,所以如果两者都尝试升级,只有一个应该通过。我仍然希望多个读者使用 shared_lock,如果是时候切换到唯一锁,我可能不得不使用 upgrade_lock,仅此而已。我没有看到“可升级锁”的使用,如果以后不升级为独占,则只允许一个读取器,此时我不太了解只有一个读取器的升级锁的用例,请帮帮我?
-
@user2300947 如果写锁是独占的而另一个持有读锁,如何通过?请参阅我的“答案”,这并不是真正的答案。
标签: c++ multithreading c++11 boost boost-thread