多线程程序,问题是:我有一个线程向量,在这里我推回我创建的每一个线程,我想做一种“偷工调度”,以这样一种方式,当一个线程被连接,所以我假设他的工作被终止,我从线程向量中删除它,我推回一个新线程给他另一个任务。 问题是,当我尝试在连接后擦除线程时,我得到了“terminate()”,因此我假设我正在擦除仍在工作的线程,即使我的目标是只擦除已经连接的线程。 我错在哪里?
vector<thread> tids;
const int nw = atoi(argv[1]); //number of worker
//Just erase the thread that has been joined
void erasePosition(thread &t, vector<thread> &threads){
for(int i=0;i<threads.size();i++){
if(t.get_id()==threads[i].get_id()) {
threads.erase(threads.begin()+i);
}
}
}
//Assign job to threads
for (int i = 0; i < nw; i++) {
tids.push_back(thread(solveSubTree, ref(works[i]), ref(nw)));
}
//
for (thread &t : tids) {
t.join();
erasePosition(t,tids);
cout << " tids.size() = " << tids.size() << endl;
}
在清除中间线程之前,我看到程序正确地执行,例如,如果我用4个线程执行程序,当我尝试清除第二个线程时,它会调用“terminate()”,而如果我用8个线程执行程序,当我尝试清除第四个线程时,它会终止,也许它会对你有用。
确切的错误是:在抛出“std::system_error”实例what():无效参数后调用terminate
for (thread &t : tids) {
范围迭代是使用来自底层容器的迭代器实现的。 一个简单的Google搜索给出了等价的代码,它从容器中获得开始和结束迭代器,然后在这个序列上迭代。
erasePosition(t,tids);
此时,内部迭代器正在引用这个向量中传递给eraseposition()
的值。
eraseposition
()有效地擦除
()向量中的此值。
但是,向量中值上的erase()
“在擦除点处或之后使迭代器和引用无效,包括end()迭代器”。 当然,这将包括T
值的迭代器。 从这一点开始,范围迭代成为未定义的行为。
胶囊摘要:这与线程无关。 无论向量中有什么,都不能对向量进行范围迭代,擦除向量中的值,然后继续进行范围迭代。 你需要用其他的方式来完成你的任务。 这将适用于任何其他容器,它使迭代器对从容器中移除的值无效(而您的家庭作业将是弄清楚是否有任何类型的容器实际上允许它)。
这可能是也可能不是你坠机的唯一原因。 可能还有其他原因,但是因为您没有提供一个最小的可复制示例,所以不可能确定这一点。