std::thread 不是全局变量,但在到达创建它的函数末尾时不会超出范围?

Posted

技术标签:

【中文标题】std::thread 不是全局变量,但在到达创建它的函数末尾时不会超出范围?【英文标题】:std::thread that isn't a global variable but doesn't go out of scope when the end of the function that created it is reached? 【发布时间】:2018-09-06 04:40:58 【问题描述】:

所以我遇到了一些似乎违背了std::thread 目的的东西,或者至少使它不那么方便了。

假设我想生成一个std::thread 来执行一次任务,之后不想再担心它。我在函数末尾附近创建了这个thread,所以std::thread 很快就会超出范围,就我而言,可能是在thread 仍在运行时。这会产生几个解决方案(或至少我知道的)的问题。

我可以:

A) 将std::thread 设为全局变量,这样它就不会超出范围。

B) 在std::thread 上调用join(),这违背了产生线程的目的。

还有其他的(希望是更好的)处理这种情况的方法吗?

【问题讨论】:

如果您不关心任务,为什么要首先启动它? std::thread 对象被销毁有什么问题?就像std::fstream 是文件一样,它们都是线程,它们都只是资源的句柄,而不是资源本身。另外,为什么它是 std::thread 很重要,你将如何处理不同类型的对象,比如 std::string 这里的问题是你永远不知道任务何时完成,或者它是否完成。因此,您的程序甚至可能在您的线程开始工作之前终止。这种方法主要适用于可选任务。此外,如果您的任务在没有任何同步的情况下修改全局数据,您就会面临各种令人讨厌的后果。 @EdwardSeverinsen 当然。我只是想说,我认为最好将多线程方面排除在管理对象生命周期之外。您正在寻找的只是存储线程对象的地方。它可以是任何对象,即使不涉及线程,也可以处理它的生命周期。将问题分解为更小的部分。 销毁std::thread“导致在线程上调用终止()”并非如此,它“导致终止()被调用”,终止您的进程。 【参考方案1】:

你想要的是std::thread::detach。

它将实际的执行线程和std::thread 对象解耦,允许您在不加入线程的情况下销毁它。

【讨论】:

你必须小心分离的线程。你如何处理异常?如何知道/控制线程是否正在运行或已完成? @AchimGuetlein std::threads 在抛出异常时终止,无论它们是否分离。要与线程进行通信,您拥有所有常用机制 - std::futurestd::mutex、原子等 - 同样,它们不依赖于 std::thread 对象 你是对的。有办法处理所有这些问题。我的观点是,如果你不解决这些问题,你可能会遇到麻烦。如果你这样做,使用std::async返回的std::future可能会更简单【参考方案2】:

您可以使用std::async

async 异步运行函数 f (可能在一个单独的线程中,它可能是线程池的一部分)并返回一个 std::future ,它最终将保存该函数调用的结果。

由于你没有提到需要获取线程的结果,所以没有必要获取future。

正如 cmets 中所指出的,std::future 的析构函数在任何情况下都会阻塞,因此您必须将其移动到某个全局对象(并手动管理未使用期货的删除),或者您可以将其移动到异步调用函数的本地范围。

【讨论】:

他没有提到他想得到线程的结果。所以没有必要获得未来。 但是如果 async 的返回值没有分配给未来呢? @P.W 也阻塞,见here std::async的返回值 std::future,其析构函数会阻塞。【参考方案3】:

其他首选选项是允许线程使用任务队列中的任务。为此,将作业拆分为任务块并提供给工作线程。为避免轮询,请选择 condition_variable。

std::thread([&]()
                    while(running) // thread loop
                     
                       // consume tasks from queue
                    
                 ).detach();

【讨论】:

以上是关于std::thread 不是全局变量,但在到达创建它的函数末尾时不会超出范围?的主要内容,如果未能解决你的问题,请参考以下文章

可以从 Windows DLL 中的全局变量创建/销毁 std::threads 吗?

std::thread 和 std::cin.get

分离的 std::thread 终止后是不是需要删除?

如何判断我们是不是在主线程中运行?

一旦std:thread进入C ++ Ox,pthreads是不是会过时[关闭]

使用 std::thread 的 C++ 多线程应用程序在 Windows 上运行良好,但在 Ubuntu 上运行良好