在C++11中从外部终止线程

vwkv1x7d  于 2023-01-15  发布在  其他
关注(0)|答案(1)|浏览(224)

我在我的C++11代码中运行多个线程,线程体是使用lambda函数定义的,如下所示。

// make connection to each device in a separate child thread
std::vector<std::thread> workers;
for(int ii = 0; ii < numDev; ii++)
{    
    workers.push_back(std::thread([=]() {  // pass by value

     // thread body

    }));
}

// detach from all threads
std::for_each(workers.begin(), workers.end(), [](std::thread &t) {
    t.detach();
});

// killing one of the threads here?

我分离了所有的子线程,但是在worker向量中保留了每个子线程的引用。我如何在以后的代码中杀死其中一个线程?
here中的帖子建议使用std::terminate(),但我想它在我的情况下没有用处。

niwlg2el

niwlg2el1#

首先,不要使用原始的std::thread,它们很少是一个好主意,就像手动调用newdelete,或者在io代码中弄乱原始的缓冲区和长度计数器--错误等待发生。
第二,不是终止线程,而是为线程任务提供一个函数或原子变量,说明工作者应该在什么时候终止自己。
工作者定期检查它的“我应该死吗”状态,如果是,它会清理自己并死亡。
然后简单地向工人发出死亡信号,并等待它这样做。
这确实需要工作线程的工作,如果工作线程执行了一些不能被中断的任务,并且持续了很长时间,那么它就不工作了。不要执行那些不能被中断并且持续很长时间的任务。
如果您必须执行这样的任务,请在不同的进程中执行,并来回整理结果。但是现代操作系统倾向于使用异步API来代替IO任务的同步API,如果您小心的话,这些API会导致任务中止。
在线程处于任意状态时终止线程会将程序置于未知和未定义的执行状态。例如,它可能持有互斥锁,并且在标准库调用中从不释放它。但实际上,它可以做任何事情。
一般来说,分离线程也是一个坏主意,因为除非你神奇地知道它们已经完成了(很困难,因为你分离了它们),否则主结束之后发生的事情是实现定义的。
跟踪你的线程,就像你跟踪你的内存分配一样,但更多。使用消息告诉线程杀死自己。连接线程来清理它们的资源,可能使用 Package 器中的条件变量来确保你在线程基本完成之前不连接。考虑使用std::async代替原始线程,并在进一步的抽象中 Package std::async本身。

相关问题