gpt4 book ai didi

c++ - 在什么时候将 unique_lock 与 shared_mutex 一起使用?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:42:27 30 4
gpt4 key购买 nike

通常,当使用“普通”互斥量时,您会像在 remove1() 中那样使用它。但是,现在有了 shared_lockunique_lock,是否应该先使用共享锁,只有在必要时才使用唯一锁?请注意,当模型不存在时,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_);

仅仅因为两个操作是单独的原子操作并不意味着一个紧接着另一个操作代表一个原子序列。一旦你放弃了一把锁,你就放弃了它。如果该互斥锁保护对容器的访问,则没有什么可以阻止您拥有的迭代器失效。

您要做的是让内部 unique_lock 以独占模式自动升级外部 shared_lock。这根本无法在 C++17 中完成。

当然,在离开 if block 之前,您永远不会重新锁定 shared_lock,因此在删除一个元素后,您就有麻烦了。

这忽略了一个事实,即每当您从任一循环中删除 一个元素时,您将跳过下一个。 erase 返回的迭代器指向下一个元素,循环头中的 ++it 将跳过它。两个函数都是如此。

但无论如何,shared_mutex 的总体目的是允许多个读取器但只允许一个修饰符。您的整个操作实际上是一个修改操作。它可能是有条件地修改,但原子地它是一个修改操作。您想要的是让每个人都能看到操作前的列表,或者让每个人都能看到所有匹配元素都被删除后的列表。在您修改列表时,任何人都不应看到它。

所以它应该使用独占访问。

关于c++ - 在什么时候将 unique_lock 与 shared_mutex 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51074037/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com