std::vector<std::thread> threadList;
然后我创建一个线程并将其推送到vector
。
threadList.push_back(std::thread([]() { ... }));
thread
完成执行后如何从threadList
vector
删除lambda function?
修改
我想出了一些解决方案;在线程lambda function返回之前,它会遍历vector
以查找ID与this_thread::get_id()
的匹配。
通过Visual Studio逐行调试,我发现它在ID中找到匹配并执行了erase函数,但是只要threadList.erase(threadList.begin() + index);
执行,我就会遇到未处理的异常线程的解构函数。
我写了一小段代码来复制这个错误。
vector<thread> threadList;
threadList.push_back(thread([]() {
Sleep(1000);
threadList.erase(threadList.begin());
}));
Sleep(2000);
//for_each(threadList.begin(), threadList.end(), mem_fn(&thread::detach));
//threadList.clear();
此代码会生成以下屏幕截图。
答案 0 :(得分:2)
一个选项是让lambda在退出时异步删除线程。例如:
std::vector<std::thread> threadList;
std::mutex threadMutex;
...
void removeThread(std::thread::id id)
{
std::lock_guard<std::mutex> lock(threadMutex);
auto iter = std::find_if(threadList.begin(), threadList.end(), [=](std::thread &t) { return (t.get_id() == id); });
if (iter != threadList.end())
{
iter->detach();
threadList.erase(iter);
}
}
...
{
std::lock_guard<std::mutex> lock(threadMutex);
threadList.push_back(
std::thread([]() {
...
std::async(removeThread, std::this_thread::get_id());
})
);
}
可替换地:
std::vector<std::thread> threadList;
std::mutex threadMutex;
...
void removeThread(std::thread::id id)
{
std::lock_guard<std::mutex> lock(threadMutex);
auto iter = std::find_if(threadList.begin(), threadList.end(), [=](std::thread &t) { return (t.get_id() == id); });
if (iter != threadList.end())
{
iter->join();
threadList.erase(iter);
}
}
...
{
std::lock_guard<std::mutex> lock(threadMutex);
threadList.push_back(
std::thread([]() {
...
std::thread(removeThread, std::this_thread::get_id()).detach();
})
);
}
可替换地:
std::vector<std::thread> threadList;
std::mutex threadMutex;
std::list<std::thread::id> threadFreeList;
std::mutex threadFreeMutex;
std::condition_variable threadFreeCV;
std::thread monitor([]() {
while (... /* app is not terminated */)
{
std::unique_lock<std::mutex> lock(threadFreeMutex);
threadFreeCV.wait(lock);
std::lock_guard<std::mutex> lock2(threadMutex);
auto iter = threadFreeList.begin();
while (iter != threadFreeList.end())
{
auto id = *iter;
auto found = std::find_if(threadList.begin(), threadList.end(), [=](std::thread &t) { return (t.get_id() == id); });
if (found != threadList.end())
{
found->join();
threadList.erase(found);
}
iter = threadFreeList.erase(iter);
}
}
});
...
{
std::lock_guard<std::mutex> lock(threadMutex);
threadList.push_back(
std::thread([]() {
...
std::unique_lock<std::mutex> lock(threadFreeMutex);
threadFreeList.push_back(std::this_thread::get_id());
threadFreeCV.notify_one();
})
);
}
答案 1 :(得分:0)
为什么在分离线程时需要这个线程向量?
// Scope that outlives the threads
boost::barrier out_barrier(N_threads+1);
...
// Starting the threads
for(int i = 0; i < N_threads; i++) {
std::thread th([&out_barrier]() {
...do the job...
out_barrier.wait();
});
th.detach();
}
...
// Wait for threads to finish
out_barrier.wait();
线程不可连接,因此调用析构函数是安全的。 在这种情况下,同步是不可避免的。在我的例子中,它用于连接所有线程,如果你有一个线程向量,你需要同步对向量的访问,所以它都是一样的。