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

Ale*_*r V 121 c++ multithreading c++11

我不需要正确终止线程,或使其响应"终止"命令.我有兴趣使用纯C++ 11强制终止线程.

How*_*ant 124

  1. 你可以std::terminate()从任何线程调用,你所指的线程将强制结束.

  2. 您可以安排~thread()在目标线程的对象上执行,而不需要介入join()也不detach()对该对象执行.这与选项1具有相同的效果.

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

选项1和2不会泄漏进程内资源,但它们会终止每个线程.

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

C++ 11中没有可移植的方式(我知道)在多线程程序中非合作地杀死单个线程(即没有杀死所有线程).设计这样的功能没有动力.

A std::thread可能有这个成员函数:

native_handle_type native_handle();
Run Code Online (Sandbox Code Playgroud)

您可以使用它来调用依赖于操作系统的函数来执行您想要的操作.例如,在Apple的操作系统上,此功能存在并且native_handle_type是一个pthread_t.如果您成功,您可能会泄漏资源.

  • @ChrisDodd Counter +1,这正是他在答案中写的. (69认同)
  • 是的。选项 1 和 2 不会泄漏进程内资源,但它们会终止*每个*线程。不知何故,当你必须解释这个笑话时,它就不那么有趣了......;-) (6认同)
  • 你也可以调用`exit()`或`abort()`来达到相同的整体效果. (5认同)
  • #1 是个笑话,@ChrisDodd 是对的。这个笑话在#3 下第一句的答案中有解释。另请参阅 Nanno Langstraat 的回答及其下方的评论。 (3认同)
  • 轻微的挑剔_"不会泄漏进程内资源"_:虽然操作系统在杀死进程后将回收所有资源当然是正确的,但就程序而言,资源已经泄漏.这通常是无关紧要的,但在某些情况下可能仍然是一个问题.`std :: terminate`既不调用静态析构函数也不刷新输出缓冲区,因此释放资源的顺序没有明确定义,也不保证用户可以看到任何数据或写入永久存储,甚至一致和完整. (2认同)
  • std::terminate() 不会杀死整个程序吗? (2认同)

Nan*_*aat 38

@Howard Hinnant的答案既正确全面.但是如果它被读得太快可能会被误解,因为std::terminate()(整个过程)碰巧与@AlexanderVX想到的"终止"同名(1个线程).

总结:"终止1个线程+强力(目标线程不合作)+纯C++ 11 =没办法."

  • 啊,我的#1真的好笑.您不必指定要强制结束的线程.系统只是神奇地知道你想强行结束哪一个并且做到了! (12认同)
  • 是的,`std :: terminate()`答案就像一个经典的恶作剧Djinn故事; 它满足了OP对这封信的所有愿望,尽管可能不是他*的意思*.低调的幽默让我微笑.:-) (6认同)
  • 只需要防止无辜的 C++ 新手把希望寄托得太远/太久。 (3认同)
  • 优雅地说。:-) (2认同)

Dor*_*Ari 15

我猜需要杀死的线程要么处于任何一种等待模式,要么在做一些繁重的工作。我建议使用“天真”的方式。

定义一些全局布尔值:

std::atomic_bool stop_thread_1 = false;
Run Code Online (Sandbox Code Playgroud)

将以下代码(或类似代码)放在几个关键点,这样会导致调用堆栈中的所有函数返回,直到线程自然结束:

if (stop_thread_1)
    return;
Run Code Online (Sandbox Code Playgroud)

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

stop_thread_1 = true;
thread1.join ();
stop_thread_1 = false; //(for next time. this can be when starting the thread instead)
Run Code Online (Sandbox Code Playgroud)

  • 但是,如果线程正在执行繁忙的阻塞作业,例如“curl”命令(需要很长时间执行或执行其他命令),该怎么办?而这个curl命令(读取libcurl库)是线程中的阻塞调用。我没有 while 循环或其他东西来检查“stop_thread_1”。 (6认同)

Zar*_*trA 11

这个问题实际上具有更深层次的性质,对多线程概念的一般理解将为您提供有关此主题的见解.事实上,没有任何语言或任何操作系统为您提供异步突然线程终止的功能,而没有警告不使用它们.所有这些执行环境都强烈建议开发人员,甚至需要在协作或同步线程终止的基础上构建多线程应用程序.这个共同决策和建议的原因是它们都建立在相同的通用多线程模型的基础之上.

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

多处理假定将整个执行环境拆分为由操作系统控制的一组完全隔离的进程.进程合并并隔离执行环境状态,包括进程的本地内存和其中的数据以及所有系统资源,如文件,套接字,同步对象.隔离是该过程的一个至关重要的特征,因为它限制了过程边界的故障传播.换句话说,没有一个进程可以影响系统中任何其他进程的一致性.对于过程行为也是如此,但是受限制较少且模糊的方式较多.在这样的环境中,任何进程都可以在任意"任意"时刻被杀死,因为首先每个进程都是隔离的,其次,操作系统对进程使用的所有资源都有完整的知识,并且可以在不泄漏的情况下释放所有进程,最后进程将被终止操作系统并非真正处于任意时刻,而是处于众所周知的过程状态的明确定义点的数量.

相反,多线程假设在同一进程中运行多个线程.但是所有这些线程都共享相同的隔离盒,并且没有任何操作系统控制进程的内部状态.因此,任何线程都能够改变全局进程状态并破坏它.同时,众所周知线程状态可以安全地杀死线程的点完全取决于应用程序逻辑,并且对于操作系统和编程语言运行时都不知道.因此,任意时刻的线程终止意味着在其执行路径的任意点杀死它,并且很容易导致进程范围内的数据损坏,内存和处理泄漏,线程泄漏和自旋锁以及其他进程内同步原语留在关闭状态阻止其他线程进行.

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

  • 这不是一个非常有用的答案.多处理在这里不相关,关于多线程的观察是相当广泛的. (7认同)
  • 我想说和详细说的是,多线程模型没有提供强制终止线程的正式方法。C ++希望遵循清晰的模型,包括内存模型,多线程模型等。强制终止线程的方法本质上是不安全的。如果强制C ++标准委员会将其添加到C ++中,则将使用下一条语句“方法Terminate()终止线程执行。行为未定义。”,这听起来像是“制造了一些魔术,并且(可能)终止了线程” ”。 (4认同)

boy*_*ang 8

使用OS依赖函数终止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.

  • 不不不!这是行不通的!请参阅此处:/sf/answers/5067132521/ (2认同)