以下只是一个简单的程序,测试使用两个线程插入一个哈希表。测试时不使用锁。
#include <iostream>
#include <unordered_map>
#include <thread>
using namespace std;
void thread_add(unordered_map<int, int>& ht, int from, int to)
{
for(int i = from; i <= to; ++i)
ht.insert(unordered_map<int, int>::value_type(i, 0));
}
void test()
{
unordered_map<int, int> ht;
thread t[2];
t[0] = thread(thread_add, ht, 0, 9);
t[1] = thread(thread_add, ht, 10, 19);
t[0].join();
t[1].join();
std::cout << "size: " << ht.size() << std::endl;
}
int main()
{
test();
return 0;
}
但是编译的时候有错误。
$ g++ -std=c++11 -pthread test.cpp
...
/usr/include/c++/4.8.2/functional:1697:61: error: no type named ‘type’ in ‘class std::result_of<void (*(std::unordered_map<int, int>, int, int))(std::unordered_map<int, int>&, int, int)>’
typedef typename result_of<_Callable(_Args...)>::type result_type;
...
花了一段时间,但仍然无法纠正。谢谢。
最佳答案
我可以使用 MSVC2013 成功编译您的代码。但是,thread()
可以将其参数的拷贝传递给新线程。这意味着如果您的代码将在您的编译器上编译,每个线程都将使用自己的 ht
拷贝运行,因此最后,main
的 ht
将为空。
GCC 无法编译这个奇怪的消息。您可以通过使用带有线程的引用包装器来摆脱它:
t[0] = thread(thread_add, std::ref(ht), 0, 9);
t[1] = thread(thread_add, std::ref(ht), 10, 19);
这将成功编译。线程使用的每个引用都将引用同一个对象。
但是,您很有可能会遇到一些运行时错误或意外结果。这是因为两个线程同时尝试插入 ht
。但是 unordered_map
不是线程安全的,因此这些 racing conditions 可能会导致 ht
达到不稳定状态(即 UB,即潜在的 segfault)。
为了让它正常运行,你必须保护你的并发访问:
#include <mutex>
...
mutex mtx; // to protect against concurent access
void thread_add(unordered_map<int, int>& ht, int from, int to)
{
for (int i = from; i <= to; ++i) {
std::lock_guard<std::mutex> lck(mtx); // protect statements until end of block agains concurent access
ht.insert(unordered_map<int, int>::value_type(i, 0));
}
}
关于c++:错误:在'class std::result_of<void (*(std::unordered_map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28950835/