[英]At what point to use unique_lock with shared_mutex?
Typically, when using a "normal" mutex, you would use it as in remove1()
. 通常,在使用“普通”互斥锁时,您可以像在
remove1()
一样使用它。 However, now with shared_lock
and unique_lock
, should you use a shared lock first and the unique lock only when necessary? 但是,现在使用
shared_lock
和unique_lock
,您是否应首先使用共享锁,并且仅在必要时使用唯一锁? Note that remove()
may not need to unique_lock
when the model does not exist. 请注意,当模型不存在时,
remove()
可能不需要unique_lock
。
void remove1(int id) {
std::unique_lock<std::shared_mutex> lock(mutex_);
for (auto it = models_.begin(); it != models_.end(); ++it)
if ((*it)->getId() == id)
{
it = models_.erase(it);
return;
{
}
void remove2(int id) {
std::shared_lock<std::shared_mutex> sharedLock(mutex_);
for (auto it = models_.begin(); it != models_.end(); ++it)
if ((*it)->getId() == id)
{
sharedLock.unlock();
std::unique_lock<std::shared_mutex> uniqueLock(mutex_);
models_.erase(it);
return;
}
}
sharedLock.unlock(); std::unique_lock<std::shared_mutex> uniqueLock(mutex_);
Just because two operations are individually atomic does not mean that one followed by the other represents an atomic sequence. 仅仅因为两个操作是单独原子的并不意味着一个跟随另一个代表原子序列。 Once you give up a lock, you give it up .
一旦你放弃锁定,你就放弃了 。 If that mutex guards access to the container, there's nothing preventing the iterator you have from being invalidated.
如果该互斥锁保护对容器的访问,则没有任何东西阻止您使迭代器失效。
What you're trying to do is have the inner unique_lock
atomically upgrade the outer shared_lock
in exclusive mode. 您要做的是让内部
unique_lock
以独占模式原子升级外部shared_lock
。 That can't be done in C++17 at all. 这完全不能在C ++ 17中完成。
And of course, you never re-lock the shared_lock
before you leave the if
block, so after erasing one element, you're in trouble. 当然,在离开
if
块之前,你永远不会重新锁定shared_lock
,因此在擦除一个元素之后,你就遇到了麻烦。
And that ignores the fact that whenever you erase
an element from either of your loops, you'll skip the next one. 而且忽略了这样一个事实:无论何时从你的任何一个循环中
erase
一个元素,你都会跳过下一个循环。 The iterator returned by erase
points to the next element, and your ++it
in the loop header will skip it. 迭代器由
erase
点返回到下一个元素,而你在循环头中的++it
跳过它。 This is true of both functions. 两种功能都是如此。
But in any case, the overall purpose of shared_mutex
is to permit multiple readers but only one modifier. 但无论如何,
shared_mutex
的总体目的是允许多个读者但只允许一个修饰符。 Your entire operation is really a modification operation. 您的整个操作实际上是一个修改操作。 It may be conditionally modifying, but atomically it is a modification operation.
它可能是有条件的修改,但在原子上它是一个修改操作。 What you want is for everyone to either see the list as it was before the operation or for everyone to see the list as it was after all matching elements are erased.
你想要的是让每个人都能看到在操作之前的列表,或者让每个人都看到列表,因为在删除了所有匹配的元素之后 。 Nobody should ever see the list while you're modifying it.
在修改列表时,没有人会看到列表。
So it should use exclusive access. 所以它应该使用独占访问。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.