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

9fkzdhlc  于 2023-02-20  发布在  其他
关注(0)|答案(7)|浏览(656)

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

4xrmg8kj

4xrmg8kj1#

1.您可以从任何线程调用std::terminate(),您所引用的线程将强制结束。
1.您可以安排~thread()在目标线程的对象上执行,而不在该对象上插入join()detach(),这与选项1的效果相同。
1.你可以设计一个异常,它有一个抛出异常的析构函数,然后安排目标线程在它被强制终止时抛出这个异常,这个问题的难点是让目标线程抛出这个异常。
选项1和2不会泄漏进程内资源,但它们会终止 * 每个 * 线程。
选项3可能会泄漏资源,但它是部分合作的,因为目标线程必须同意抛出异常。
在C++11中没有可移植的方法(据我所知)来非协作地杀死多线程程序中的单个线程(即不杀死所有线程),也没有设计这样一个特性的动机。
std::thread可以具有以下成员函数:

native_handle_type native_handle();

您可以使用此函数调用操作系统相关函数来执行您想要的操作。例如,在Apple的操作系统上,此函数存在,并且native_handle_typepthread_t。如果您成功调用,则很可能会泄漏资源。

kcrjzv8t

kcrjzv8t2#

@霍华德Hinnant的回答是正确的 * 和 * 全面的。但是如果读得太快,可能会被误解,因为std::terminate()(整个进程)碰巧与@ Alexandria V想到的“终止”(1个线程)同名。
总结:“终止1个线程+强制(目标线程不合作)+纯C++11 =没有办法。”

wf82jlnq

wf82jlnq3#

我猜需要被杀死的线程要么处于任何类型的等待模式,要么正在做一些繁重的工作。我会建议使用“天真”的方式。
定义一些全局布尔值:

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)
xuo3flqw

xuo3flqw4#

使用操作系统相关函数终止C++线程的技巧:

  1. std::thread::native_handle()只能在调用join()detach()之前获取线程的有效本机句柄类型。之后,native_handle()返回0-pthread_cancel()将进行核心转储。
    1.为了有效地调用本机线程终止函数(例如pthread_cancel()),您需要在调用std::thread::join()std::thread::detach()之前保存本机句柄。这样您的本机终止符总是有一个有效的本机句柄可供使用。
    更多解释请参考:http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread.
ymzxtsji

ymzxtsji5#

这个问题实际上有更深的本质,对多线程概念的良好理解一般会让你对这个主题有更深入的了解。事实上,没有任何语言或任何操作系统为你提供异步突然线程终止而不警告不要使用它们的设施。所有这些执行环境都强烈地建议开发者甚至要求在协作或并行的基础上构建多线程应用程序同步线程终止。这种常见的决策和建议的原因是它们都是建立在相同的通用多线程模型的基础上的。
让我们比较一下多处理和多线程的概念,以便更好地理解第二个概念的优点和局限性。
多处理假设将整个执行环境分割成一组由操作系统控制的完全隔离的进程。进程合并并隔离执行环境状态,包括进程的本地内存和其中的数据,以及所有系统资源,如文件、套接字、同步对象。隔离是进程的一个至关重要的特性。因为它限制了错误通过进程边界的传播。换句话说,没有一个进程可以影响系统中任何另一个进程的一致性。2进程行为也是如此,但限制较少,方式更模糊。在这样的环境中,任何进程都可以在任何"任意"时刻被杀死,因为首先每个进程都是孤立的,其次操作系统对进程使用的所有资源都有充分的了解,并且可以在不泄漏的情况下释放所有资源,最后进程会被操作系统杀死,而不是真正在任意时刻。而是取决于工艺状态众所周知的明确定义的点的数量。
与此相反,多线程假设在同一进程中运行多个线程。2但是所有这些线程共享同一个隔离盒,并且没有任何操作系统控制进程的内部状态。3结果,任何线程都能够改变全局进程状态并破坏它。同时,已知线程的状态对于杀死线程是安全的点完全取决于应用逻辑,并且对于操作系统和应用程序都是未知的。结果,线程在任意时刻终止意味着在其执行路径的任意点杀死它,并且可以容易地导致进程范围内的数据损坏、存储器和句柄泄漏、线程泄漏和自旋锁以及其它进程内同步原语处于关闭状态,从而阻止其它线程进行。
因此,常见的方法是强制开发者实现同步或协作线程终止,其中一个线程可以请求其他线程终止,并且在明确定义的点中的其他线程可以检查该请求,并且从明确定义的状态开始关闭过程,以安全和一致的方式释放所有全局系统范围资源和局部进程范围资源。

ar5n3qh5

ar5n3qh56#

可能是TerminateThread?仅在Windows中。

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

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

iugsix8n

iugsix8n7#

你不能使用C++ std::thread析构函数来终止多线程程序中的单个线程。下面是std::thread析构函数的相关代码片段,位于thread头文件(Visual C++)中:

~thread()
{
  if (joinable())
    std::terminate();
}

如果调用可连接线程的析构函数,则析构函数调用作用于进程的std::terminate();不在线程上,否则,它什么也不做。
可以使用OS函数"强制终止线程"(C++11 std::thread)。在Windows上,您可以使用TerminateThread。"TerminateThread是一个危险的函数,只能在最极端的情况下使用。"-Microsoft|学习。

TerminateThread(tr.native_handle(), 1);

为了使TerminateThread生效,之前不应该调用join()/detach(),因为这样的调用会使native_handle()无效。
您应该在TerminateThread之后调用detach()(或join())。否则,如第1段所述,线程析构函数std::terminate()将被调用,整个进程将被终止。
示例:

#include <iostream>
#include <thread>
#include <Windows.h>

void Work10Seconds()
{
    std::cout << "Work10Seconds - entered\n";

    for (uint8_t i = 0; i < 20; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        std::cout << "Work10Seconds - working\n";
    }

    std::cout << "Work10Seconds - exited\n";
}

int main() {
    std::cout << "main - started\n";

    std::thread tr{};

    std::cout << "main - Run 10 seconds work thread\n";
    tr = std::thread(Work10Seconds);

    std::cout << "main - Sleep 2 seconds\n";
    std::this_thread::sleep_for(std::chrono::seconds(2));

    std::cout << "main - TerminateThread\n";
    TerminateThread(tr.native_handle(), 1);
    tr.detach(); // After TerminateThread

    std::cout << "main - Sleep 2 seconds\n";
    std::this_thread::sleep_for(std::chrono::seconds(2));

    std::cout << "main - exited\n";
}

输出:

main - started
main - Run 10 seconds work thread
main - Sleep 2 seconds
Work10Seconds - entered
Work10Seconds - working
Work10Seconds - working
Work10Seconds - working
main - TerminateThread
main - Sleep 2 seconds
main - exited

相关问题