提问者:小点点

如何删除连接后的线程?


多线程程序,问题是:我有一个线程向量,在这里我推回我创建的每一个线程,我想做一种“偷工调度”,以这样一种方式,当一个线程被连接,所以我假设他的工作被终止,我从线程向量中删除它,我推回一个新线程给他另一个任务。 问题是,当我尝试在连接后擦除线程时,我得到了“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


共1个答案

匿名用户

for (thread &t : tids) {

范围迭代是使用来自底层容器的迭代器实现的。 一个简单的Google搜索给出了等价的代码,它从容器中获得开始和结束迭代器,然后在这个序列上迭代。

    erasePosition(t,tids);

此时,内部迭代器正在引用这个向量中传递给eraseposition()的值。

eraseposition()有效地擦除()向量中的此值。

但是,向量中值上的erase()“在擦除点处或之后使迭代器和引用无效,包括end()迭代器”。 当然,这将包括T值的迭代器。 从这一点开始,范围迭代成为未定义的行为。

胶囊摘要:这与线程无关。 无论向量中有什么,都不能对向量进行范围迭代,擦除向量中的值,然后继续进行范围迭代。 你需要用其他的方式来完成你的任务。 这将适用于任何其他容器,它使迭代器对从容器中移除的值无效(而您的家庭作业将是弄清楚是否有任何类型的容器实际上允许它)。

这可能是也可能不是你坠机的唯一原因。 可能还有其他原因,但是因为您没有提供一个最小的可复制示例,所以不可能确定这一点。