如何在C ++ 11中终止线程?


Answers:


137
  1. 您可以std::terminate()从任何线程进行调用,并且您所引用的线程将强制终止。

  2. 您可以安排~thread()在目标线程的对象上执行,而无需干预join()detach()对该对象执行。这将与选项1相同。

  3. 您可以设计一个具有析构函数的异常,该析构函数会引发异常。然后安排目标线程在要强制终止该异常时引发此异常。这方面的棘手部分是使目标线程抛出此异常。

选项1和2不会泄漏进程内资源,但它们会在每次终止时终止线程。

选项3可能会泄漏资源,但部分协作是因为目标线程必须同意引发异常。

在C ++ 11中(我知道),没有一种可移植的方式来非合作地杀死多线程程序中的单个线程(即不杀死所有线程)。没有动机去设计这样的功能。

std::thread可具有该成员函数:

native_handle_type native_handle();

您可能可以使用它来调用依赖于OS的函数以执行所需的操作。例如,在Apple的OS上,此功能存在并且native_handle_typepthread_t。如果成功,则很可能会泄漏资源。


2
轻描淡写地“不要泄漏进程内资源”:虽然确实可以肯定,操作系统将在杀死进程后回收所有资源,但就程序而言,资源泄漏的。这通常无关紧要,但在某些情况下可能仍然是一个问题。std::terminate既不调用静态析构函数,也不刷新输出缓冲区,所以释放资源的顺序不明确,也不保证用户可以看到任何数据或将其写入永久存储,甚至一致和完整。
戴蒙2015年

6
您也可以调用exit()abort()达到相同的整体效果。
n。代词

2
#1是个玩笑,@ ChrisDodd是对的。在#3下第一句的答案中对此笑话进行了解释。另请参阅Nanno Langstraat的答案及其下面的评论。
Howard Hinnant

43

@Howard Hinnant的回答既正确全面。但是,如果读取得太快,可能会被误解,因为std::terminate()(整个过程)恰好与@AlexanderVX想到的“终止”同名(1个线程)。

摘要:“终止1个线程+强制(目标线程不配合)+纯C ++ 11 =没办法。”


14
啊,我的#1真的很有趣。您不必指定要强制结束的线程。该系统只是神奇地知道您要强制终止哪一个并执行该操作!
Howard Hinnant 2013年

8
是的,std::terminate()答案就像一个经典的调皮的Djinn故事;它可以满足OP的所有要求,尽管可能不是他的意思。低调的幽默使我微笑。:-)
Nanno Langstraat 2014年

2
只是必须防止无辜的C ++新手将希望寄托于太远/太久。
Nanno Langstraat 2014年

2
优雅地陈述。:-)
Howard Hinnant 2014年

@NannoLangstraat dammnit ...我一直寄予厚望,直到我继续读:(..lol,哦,好吧+1都是:)
code_fodder

13

这个问题实际上具有更深的性质,并且对多线程概念有很好的理解,通常会为您提供有关此主题的见解。实际上,没有任何语言或操作系统可以为您提供异步突然终止线程的便利,而不会警告您不要使用它们。所有这些执行环境都强烈建议开发人员,甚至要求在协作或同步线程终止的基础上构建多线程应用程序。之所以采用这种通用的决策和建议,是因为它们都是基于相同的通用多线程模型构建的。

让我们比较多处理和多线程的概念,以更好地理解第二种方法的优点和局限性。

多重处理假定将整个执行环境分为由操作系统控制的一组完全隔离的进程。进程合并并隔离了执行环境状态,包括进程的本地内存和其中的数据以及所有系统资源,例如文件,套接字,同步对象。隔离是过程的一个至关重要的特征,因为它限制了过程边界传播的故障。换句话说,没有一个进程可以影响系统中任何其他进程的一致性。对于过程行为也是如此,但限制较少且模糊程度更高。在这种环境下,任何进程都可以在任何“任意”时刻被杀死,因为首先每个进程都是孤立的,其次,

相反,多线程假定在同一进程中运行多个线程。但是所有这些线程都共享同一个隔离盒,并且没有任何操作系统控制进程的内部状态。结果,任何线程都可以更改全局进程状态以及对其进行破坏。同时,众所周知,线程状态可以安全杀死线程的点完全取决于应用程序逻辑,操作系统和编程语言运行时都不知道。结果,在任意时刻终止线程意味着在其执行路径的任意点杀死它,并很容易导致整个进程的数据损坏,内存不足并处理泄漏,

因此,常见的方法是强制开发人员实施同步或协作线程终止,其中一个线程可以请求其他线程终止,而其他在定义明确的线程可以检查此请求并从定义明确的状态启动关闭过程以安全一致的方式释放所有全球系统范围的资源和本地过程范围的资源。


7
这不是一个很有帮助的答案。多处理在这里无关紧要,关于多线程的观点相当广泛。
MSalters 2015年

4
我想说和详细说的是,多线程模型没有提供强制终止线程的正式方法。C ++希望遵循清晰的模型,包括内存模型,多线程模型等。强制终止线程的方法本质上是不安全的。如果强制C ++标准委员会将其添加到C ++中,则将使用下一条语句“方法Terminate()终止线程执行。行为未定义。”,这听起来像是“制造了一些魔术,并且(可能)终止了线程” ”。
ZarathustrA 2015年

C#具有此功能。
Derf Skren

@Derf Skren“实际上,没有任何语言或操作系统为您提供异步突然终止线程的便利,而不会警告您不要使用它们。”(c)ZarathustrA“备注:重要!Thread.Abort方法应谨慎使用特别是当您调用它中止当前线程以外的其他线程时,您不知道什么代码已执行或执行失败...”(c)Microsoft链接:docs.microsoft.com/zh-cn/dotnet/ api /…
ZarathustrA

11

使用依赖于操作系统的函数终止C ++线程的提示:

  1. std::thread::native_handle()只能在调用join()或之前获取线程的有效本机句柄类型detach()。之后,native_handle()返回0- pthread_cancel()将进行coredump。

  2. 为了有效地调用本机线程终止函数(例如pthread_cancel()),您需要在调用std::thread::join()或之前保存本机句柄std::thread::detach()。这样,您的本机终结者始终可以使用有效的本机句柄。

更多解释请参考:http : //bo-yang.github.io/2017/11/19/cpp-kill-detached-thread


5

我猜想需要杀死的线程要么处于任何等待模式,要么处于繁重的工作。我建议使用“幼稚”的方式。

定义一些全局布尔值:

std::atomic_bool stop_thread_1 = false;

将以下代码(或类似代码)放在几个关键点上,以使调用堆栈中的所有函数都返回直到线程自然结束为止:

if (stop_thread_1)
    return;

然后停止另一个(主)线程中的线程:

stop_thread_1 = true;
thread1.join ();
stop_thread_1 = false; //(for next time. this can be when starting the thread instead)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.