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

我不需要正确地终止线程,也不需要让它响应一个“终止”命令。我对使用纯 C + + 11强制终止线程感兴趣。

290042 次浏览
  1. 您可以从任何线程调用 std::terminate(),您引用的线程将强制结束。

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

  3. 您可以设计一个具有析构函数的异常,该析构函数引发异常。然后安排目标线程在要强制终止该异常时引发该异常。这个异常的棘手之处在于让目标线程抛出这个异常。

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

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

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

std::thread可能具有以下成员函数:

native_handle_type native_handle();

您可以使用它来调用一个依赖于操作系统的函数来完成您想要的任务。例如,在苹果的操作系统上,这个函数是存在的,而 native_handle_typepthread_t。如果你成功了,你很可能会泄露资源。

@ 霍华德 · 希南特的答案都是正确的 还有综合。但是如果读得太快,可能会产生误解,因为 std::terminate()(整个进程)恰好与@Alexander V 想到的“终止”(1个线程)同名。

总结: “强制终止1个线程 + 目标线程不合作) + 纯 C + + 11 = 不可能。”

这个问题实际上具有更深的性质,通常对多线程概念的良好理解将为您提供关于这个主题的见解。事实上,没有任何语言或操作系统能够在没有警告的情况下为异步突然线程终止提供便利。所有这些执行环境都强烈建议开发人员,甚至要求在协作或同步线程终止的基础上构建多线程应用程序。出现这种常见决策和建议的原因是,它们都建立在相同的通用多线程模型的基础上。

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

多处理假设将整个执行环境拆分为由操作系统控制的一组完全隔离的进程。进程合并和隔离执行环境状态,包括进程的本地内存和进程内部的数据,以及所有系统资源,如文件、套接字、同步对象。隔离是过程的一个重要特征,因为它限制了过程边界的故障传播。换句话说,任何一个进程都不能影响系统中任何其他进程的一致性。对于进程行为也是如此,但是限制更少,模糊程度更高。在这样的环境中,任何进程都可以在任意时刻被杀死,因为首先每个进程都是孤立的,其次,操作系统对进程使用的所有资源都有充分的了解,可以不泄漏地释放所有资源,最后进程将被操作系统杀死,不是真的在任意时刻,而是在进程状态已知的、定义良好的点的数量上。

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

因此,通常的做法是强迫开发人员实现同步或协作线程终止,其中一个线程可以请求其他线程终止,其他线程在明确定义的点可以检查这一请求,并开始关机程序从明确定义的状态释放所有全局系统范围的资源和局部进程范围的资源,以安全和一致的方式。

使用 OS 相关函数终止 C + + 线程的提示:

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

  2. 要有效地调用本机线程终止函数(例如 pthread_cancel()) ,需要在调用 std::thread::join()std::thread::detach()之前保存本机句柄。因此,您的本机终止程序始终有一个有效的本机句柄可以使用。

详情请参阅: http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread

我猜想需要关闭的线程要么处于某种等待模式,要么正在执行一些繁重的工作。 我建议用“天真”的方式。

定义一些全局布尔值:

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)

也许终结线程? 只在窗户上。

WINBASEAPI WINBOOL WINAPI TerminateThread (HANDLE hThread, DWORD dwExitCode);

Https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-terminatethread