c++ - 从多个线程修改 unordered_map 是否安全?
问题描述
我知道有 C++ 并发 hashmap 库,例如folly。然而,天下没有免费的午餐。如果我只使用原生 STL 容器,例如 unordered_map。
示例代码有三个版本:
第一个版本:
#include "boost/asio/thread_pool.hpp"
#include "boost/thread.hpp"
#include "boost/asio.hpp"
#include <thread>
#include <unordered_map>
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
int main() {
// boost::asio::thread_pool pool(std::thread::hardware_concurrency());
boost::asio::thread_pool pool(1);
std::unordered_map<int, int> students;
srand((unsigned)time(NULL));
// std::mutex m;
for(int i = 0; i < 10000; i++) {
// boost::asio::post(pool, [&students, &m] () {
// std::lock_guard<std::mutex> lock(m);
boost::asio::post(pool, [&students] () {
students.emplace(std::make_pair(rand(), rand()));
});
}
pool.join();
for(auto item : students) {
std::cout << item.first << " " << item.second << std::endl;
}
std::cout << students.size() << std::endl;
return 0;
}
在第一个版本中,只有一个线程。所以没有任何问题。
第二个版本:
#include "boost/asio/thread_pool.hpp"
#include "boost/thread.hpp"
#include "boost/asio.hpp"
#include <thread>
#include <unordered_map>
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
int main() {
boost::asio::thread_pool pool(std::thread::hardware_concurrency());
// boost::asio::thread_pool pool(1);
std::unordered_map<int, int> students;
srand((unsigned)time(NULL));
std::mutex m;
for(int i = 0; i < 10000; i++) {
boost::asio::post(pool, [&students, &m] () {
std::lock_guard<std::mutex> lock(m);
// boost::asio::post(pool, [&students] () {
students.emplace(std::make_pair(rand(), rand()));
});
}
pool.join();
for(auto item : students) {
std::cout << item.first << " " << item.second << std::endl;
}
std::cout << students.size() << std::endl;
return 0;
}
在第二个版本中,可能会有多个线程将数据插入到一个 unordered_map 中,线程的数量取决于机器。在将数据插入 unordered_map 之前,有一个锁保证一次只有一个线程可以插入 unordered_map。第二个版本也没有任何问题。
第三个版本:
#include "boost/asio/thread_pool.hpp"
#include "boost/thread.hpp"
#include "boost/asio.hpp"
#include <thread>
#include <unordered_map>
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
int main() {
boost::asio::thread_pool pool(std::thread::hardware_concurrency());
// boost::asio::thread_pool pool(1);
std::unordered_map<int, int> students;
srand((unsigned)time(NULL));
// std::mutex m;
for(int i = 0; i < 10000; i++) {
// boost::asio::post(pool, [&students, &m] () {
// std::lock_guard<std::mutex> lock(m);
boost::asio::post(pool, [&students] () {
students.emplace(std::make_pair(rand(), rand()));
});
}
pool.join();
for(auto item : students) {
std::cout << item.first << " " << item.second << std::endl;
}
std::cout << students.size() << std::endl;
return 0;
}
在第三个版本中,多个线程将数据插入到一个 unordered_map 中。代码可以编译成功。但是,在运行相应的可执行程序时,控制台会打印“Segmentation fault (core dumped)”
在 C++11 中同时从多个线程修改 unordered_map(STL 容器)是否安全?
如果不安全,是否有任何意外的不安全行为或预期的不安全行为,不安全行为的原因是什么?
除了开源并发哈希映射库和第一版代码和第二版代码,还有其他解决方案可以在C++11中安全地从多个线程同时修改unordered_map(STL容器)吗?
解决方案
推荐阅读
- reactjs - 设备中未安装应用程序时的深度链接
- javascript - 无法在 this.props.history.push() 读取未定义的道具
- datatable - OctoberCMS 部分渲染到 MDB 数据表
- c++ - 错误:'operator<<' 不匹配(操作数类型是 'std::ostream {aka std::basic_ostream
}'和'列表') - python-3.x - 单击网站上的链接以获取带有硒的气泡中的内容
- r - ElasticNet 和 cv.glmnet 预测错误的结果
- android - 如何编程一个按钮以在反应原生中打开反应导航抽屉?
- javascript - 导出的对象在 nodejs 中未定义
- android - 是否可以通过 Android 设备中的 NFC 阅读器应用程序读取 Apple .pkpass 钱包?
- ckeditor - 每当用户粘贴任何数据时自动应用一些字体