如何在c++中终止或停止分离的线程

How to terminate or stop a detached thread in c++?

本文关键字:分离 线程 终止 c++      更新时间:2023-10-16

我对终止/停止/终止c++中分离的线程很感兴趣。如何做到这一点?

void myThread()
{
    int loop = 0;
    while(true)
    {
        std::this_thread::sleep_for(std::chrono::seconds(5));
        ++loop;
    }
}
void testThread()
{
    std::thread globalThread(myThread);
    globalThread.detach();
}
int main(void)
{
    testThread();
    for(unsigned int i=0; i < 1000; i++)
    {
        cout << "i = " << i << endl;
    }
    return 0;
}

我之所以想"停止"/"终止"globalThread(),是因为valgrind列出了这是一种"可能丢失"类型的内存泄漏(152字节)。处理这个问题的最佳方法是什么?

没有停止另一个线程的规定;无论是分离的还是可连接的。

停止线程的唯一方法是让线程从初始线程函数返回。

在这种特殊情况下,我建议进行以下更改:

  1. 不要拆开螺纹。在main()中实例化它
  2. 加上布尔值和std::mutex,布尔将初始化为false
  3. 每次通过线程的内部循环,使用std::unique_lock锁定互斥体,获取布尔值,然后解锁互斥体。在解锁互斥体之后,如果bool是true,则中断循环并返回
  4. 在main()中,退出前:锁定互斥体,将bool标志设置为true,解锁互斥体,然后加入线程

这并不完美,因为第二个线程需要长达五秒钟的时间来检查bool标志并返回。但是,这将是第一步。

没有办法干净地关闭分离的线程。这样做需要等待清理完成,并且只有在线程是可连接的情况下才能这样做。

例如,考虑一下,如果线程持有另一个线程需要获取的互斥量,以便干净地关闭。干净地关闭该线程的唯一方法是促使它释放互斥对象。这需要线程的合作。

考虑线程是否打开了一个文件并锁定了该文件。中止线程将使文件处于锁定状态,直到进程完成。

考虑线程是否持有一个互斥锁,该互斥锁保护某个共享状态,并将该共享状态暂时置于不一致状态。如果终止线程,那么互斥锁将永远不会被释放,或者互斥锁将在受保护数据处于不一致状态的情况下被释放。这可能会导致崩溃。

你需要线程的配合才能干净地关闭它。

您可以低于C++标准并使用特定于操作系统的功能,例如在设置信号掩码的同时向自己的进程发送信号,使其仅传递给分离的线程-处理程序可以设置从线程轮询的标志。如果你的主例程等待的时间超过了轮询周期加上一点,你可以猜测它应该已经终止-P.同样的一般思想可以用于任何其他信号机制,例如原子终止asap标志变量。

或者,作为最后的手段,还有pthread_cancel和类似的。请注意,像这样的异步取消通常是一件非常危险的事情——你应该小心,你终止的线程不能在任何资源被锁定/占用的代码中,否则你可能会出现死锁、泄漏和/或未定义的行为。例如,您的代码调用std::this_thread::sleep_for(std::chrono::seconds(5));——如果在间隔到期时要求操作系统进行回调,但之后要继续执行的函数使用终止线程的堆栈,该怎么办?一个安全的例子是,如果线程在你的应用程序中的循环中进行一些简单的数字运算。

否则,如果你一开始就避免分离线程,Sam的回答记录了一个替代方案。。。。

注意到"否";帮助不大:

一般来说,你会看到答案类似于";使用你自己的线程间通信";

无论这是主线程和子线程之间共享的原子bool,还是通过操作系统方法向另一个线程发出信号。

将焦点转移到你希望一个分离的线程何时死亡的细节上,而不是"谁杀人",这可能会有所帮助。

https://en.cppreference.com/w/cpp/thread/notify_all_at_thread_exit

看上面这样的代码示例帮助我处理了我正在处理的问题(主线程模糊地死去,子线程分段),我希望它能帮助你。

我认为最好的方法是创建信号处理程序

#include <iostream>
#include <csignal>
using namespace std;
void signalHandler( int signum ) {
   cout << "Interrupt signal (" << signum << ") received.n";
   // cleanup and close up stuff here  
   // terminate program  
   exit(signum);  
}
int main () {
   // register signal SIGINT and signal handler  
   signal(SIGINT, signalHandler);  
   while(1) {
      cout << "Going to sleep...." << endl;
      sleep(1);
   }
   return 0;
}

https://www.tutorialspoint.com/cplusplus/cpp_signal_handling.htm这是我得到代码的地方。您也可以使用raise函数在代码中创建信号。签出链接。

您可以通过设置分离线程的条件来终止通过指针的循环。

您也可以等待该线程,直到它使用信号量完成执行。