我遇到了在C ++ 11中运行多线程代码的问题(segfault)。这是代码:
#include <vector>
#include <thread>
std::vector<int> values;
int i;
void values_push_back()
{
values.push_back(i);
}
int main()
{
while(true)
{
std::vector<std::thread> threads;
for(i=0; i<10; ++i)
{
std::thread t(values_push_back);
threads.push_back(std::move(t));
}
for(i=0; i<10; ++i)
threads[i].join();
}
return 0;
}
这里是gdb上的回溯:http://pastebin.com/5b5TN70c
那有什么不对?
答案 0 :(得分:14)
这与移动无关。
多个线程正在同一个vector::push_back()
上执行vector
但是
vector::push_back()
不是线程安全的。对vector
的修改需要同步。
可以使用std::mutex
将来电同步到push_back()
:
std::vector<int> values;
std::mutex values_mutex;
void values_push_back()
{
values_mutex.lock();
values.push_back(i);
values_mutex.unlock();
}
此外,变量i
在没有同步的线程之间共享,这将导致竞争条件(这可能导致重复int
添加到vector
) 。考虑将int
值作为参数传递给线程以避免这种情况:
std::vector<int> values;
std::mutex values_mutex;
void values_push_back(int i)
{
values_mutex.lock();
values.push_back(i);
values_mutex.unlock();
}
for (int i = 0; i < 10; ++i)
{
threads.push_back(std::thread(values_push_back, i));
}
for (auto& t: threads) t.join();
由bamboon评论为std::lock_guard
,以确保在push_back()
抛出时释放锁定(在这种情况下只能bad_alloc()
但是vector
更改以保存具有抛出构造函数的更复杂的对象,这变得更加重要):
void values_push_back(int i)
{
std::lock_guard<std::mutex> lk(values_mutex);
values.push_back(i);
}