线程完成后从向量中删除线程

时间:2017-09-13 01:16:38

标签: c++ multithreading vector lambda

我的C ++程序中有vector thread个。

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();

此代码会生成以下屏幕截图。

enter image description here

2 个答案:

答案 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();

线程不可连接,因此调用析构函数是安全的。 在这种情况下,同步是不可避免的。在我的例子中,它用于连接所有线程,如果你有一个线程向量,你需要同步对向量的访问,所以它都是一样的。