复制/修改STL容器的副本是线程安全的
Is is thread-safe to copy/modify a copy of an STL container?
我有一个将从多个线程修改的std::map
,并且我有一个互斥锁来锁定这些写操作。但是,在长时间运行的操作期间必须偶尔使用映射,并且在整个操作期间持有锁并阻塞所有这些写操作是不好的。
我有两个问题:
- 是线程安全的执行该操作的副本上的地图,而其他线程正在写原来的?
- 是线程安全的复制地图,而其他线程正在改变它?
class Foo {
void writeToMap(Bar &bar, Baz &baz) {
// lock mutex
map[bar] = baz;
// unlock mutex
}
std::map<Bar, Baz> getMapCopy() {
// lock mutex (Is this necessary?)
std::map<Bar, Baz> copy (map);
// unlock mutex
return copy;
}
std::map<Bar, Baz> map;
};
void expensiveOperation(Foo &f) {
std::map<Bar, Baz> mapCopy = f.getMapCopy();
// Can I safely read mapCopy?
}
听起来好像复制操作本身不是线程安全的,问题是复制64位值的原子性。您复制前4个字节,而第二个4被另一个线程修改,留下不一致的8个字节。
请查看这里:复制线程安全吗?
如果你设法创建一个一致的副本,然而,我不明白为什么不…
在该代码中有未定义行为,因为您返回对局部变量的引用。一旦函数返回,这个局部变量将被解构,现在您就有了一个对被解构对象的引用。
如果你想返回一个副本,那么你必须返回的值,所以它将是例如
std::map<Bar, Baz> getMapCopy() {
return map;
}
如果您使用c++ 11标准线程库中的互斥锁,则不需要显式解锁,互斥锁将随着锁的销毁而解锁。
相关文章:
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 如何将元素添加到数组的线程安全函数?
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 异常属于C++中的线程还是进程
- C++中的线程安全删除
- C++使用params创建线程函数会导致转换错误
- 类与私有变量的其他类之间的线程安全性
- CoInitialize()在单独的线程上崩溃而不返回
- 是否可以在并行区域中为共享 2D 数组创建选定元素的线程本地副本?(共享,私有,障碍:OPenMP)
- 使用 lambda 表达式创建线程时,如何为每个线程提供自己的 lambda 表达式副本
- 提升线程问题,当一个线程与另一个线程没有相同的副本时如何共享变量?
- 免疫表中副本的设置是否安全,避免线程损坏
- C++-初始化由不同线程拥有的对象的两个副本
- 复制/修改STL容器的副本是线程安全的