通常,在使用“普通”互斥锁时,您可以像中那样使用它remove1()。但是,现在有了shared_lock和unique_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;
}
}
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)sharedLock.unlock(); std::unique_lock<std::shared_mutex> uniqueLock(mutex_);
仅仅因为两个操作各自是原子的,并不意味着一个操作后面跟着另一个操作就代表一个原子序列。一旦你放弃了锁,你就放弃了它。如果该互斥体保护对容器的访问,则没有什么可以阻止您拥有的迭代器失效。
您要做的就是让内部以独占模式unique_lock原子升级外部。shared_lock这在 C++17 中根本无法完成。
当然,在shared_lock离开该if块之前,您永远不会重新锁定,因此在擦除一个元素后,您就会遇到麻烦。
这忽略了这样一个事实:每当您erase从任一循环中获取元素时,您都会跳过下一个循环。返回的迭代器erase指向下一个元素,并且您的++it循环头将跳过它。这两个函数都是如此。
但无论如何,总体目的shared_mutex是允许多个读者,但只允许一个修饰符。你的整个操作实际上就是一个修改操作。它可能是有条件修改的,但从原子角度来说它是一个修改操作。您希望每个人都可以看到操作之前的列表,或者每个人都可以看到删除所有匹配元素之后的列表。当您修改列表时,任何人都不应该看到该列表。
所以它应该使用独占访问。
| 归档时间: |
|
| 查看次数: |
724 次 |
| 最近记录: |