【问题标题】:How to kill a running thread? [duplicate]如何杀死正在运行的线程? [复制]
【发布时间】:2012-11-08 08:40:36
【问题描述】:

可能重复:
kill thread in pthread

在包含启动线程的源代码之后,过了一会儿我想杀死它。怎么做 ? 无需对线程功能做任何改动

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

pthread_t test_thread;

void *thread_test_run (void *v) // I must not modify this function
{
    int i=1;
    while(1)
    {
       printf("into thread %d\r\n",i);
       i++; 
       sleep(1);
    }
    return NULL
}

int main()
{
    pthread_create(&test_thread, NULL, &thread_test_run, NULL);

    sleep (20);
    // Kill the thread here. How to do it?

   // other function are called here...

    return 0;
}

【问题讨论】:

  • 请注意,直截了当地“杀死”线程是个坏主意。每个线程都应该被正确地设计为从主程序中停止它。仅仅因为存在杀死线程的函数,并不意味着你应该开始以糟糕的方式设计你的线程函数。
  • 我建议查看pthread_joinpthread_attr_setdetachstate... 建立一些机制来告诉线程它现在需要退出并在线程上调用pthread_join 以清理使用的东西。
  • 我正在使用来自外部库的函数,并且该函数包含无限 while 循环。此函数在随机时间内对全局变量进行 1 次更改。所以我想在全局变量更改后杀死线程。我不再需要线程运行了
  • 如果线程函数正在执行系统调用,pthread_cancel(pthread_t thread); 是否会导致阻塞

标签: c multithreading pthreads


【解决方案1】:

你可以使用pthread_cancel()杀死一个线程:

int pthread_cancel(pthread_t thread);

请注意,线程可能没有机会进行必要的清理,例如释放锁、释放内存等。所以你应该首先使用pthread_cleanup_push()添加清理函数,这些函数将在线程被调用时调用取消。来自男人pthread_cleanup_push(3)

这些函数操作调用线程的堆栈 线程取消清理处理程序。 清理处理程序是 线程取消时自动执行的函数(或 在下述各种其他情况下); 可能,因为 例如,解锁一个互斥体,使其对其他线程可用 在这个过程中。

关于线程是否阻塞是否会被取消的问题,并不能保证,注意手册中也提到了这一点:

线程的取消类型,由 pthread_setcanceltype(3) 确定, 可以是异步的或延迟的(new 的默认值) 线程)。异步可取消性意味着线程 可以随时取消(通常是立即取消,但系统会 不保证这一点)。延期取消意味着取消 将被延迟,直到线程下一次调用一个函数 取消点。

所以这意味着唯一保证的行为是线程将在调用pthread_cancel()之后的某个时间点被取消。

注意: 如果您无法更改线程代码以添加清理处理程序,那么您唯一的其他选择就是使用pthread_kill() 终止线程,但是由于上述原因,这是一种非常糟糕的方法。

【讨论】:

  • +1 用于提及 pthread_cleanup_push()
  • 如果线程函数正在执行系统调用,pthread_cancel(pthread_t thread); 是否会导致阻塞?
  • @MohamedKALLEL 检查更新
  • @MohamedKALLEL 不,对pthread_cancel() 的调用永远不会是阻塞调用。
  • @MohamedKALLEL 我想念你的问题,没有 pthread_cancel 不会阻塞,但是如果线程在另一个调用上阻塞,例如阅读,不能保证它会立即被取消
【解决方案2】:

简短的回答是:在线程正在运行的代码的配合下,您可以使用它支持的任何方法终止它。如果没有线程正在运行的代码的合作,你甚至不应该尝试它。如果线程在你杀死它时持有一个关键锁怎么办?如果线程已分配内存并且没有其他代码可以释放该内存怎么办?

【讨论】:

  • 当且仅当线程运行的代码支持它时,您的答案才有效。否则,它可能会在线程持有关键锁或分配内存后破坏线程。正如我所说,如果代码支持它,您可以使用它支持的任何方法。但如果你不知道代码支持这一点,你甚至不应该尝试。
  • 是的,这就是pthread_cleanup_push添加支持取消线程的代码的目的。
  • 对,但他的问题是他不能更改他试图终止的代码。因此,当且仅当他试图终止的代码支持该方法时,他才能使用此方法。但他可以使用他试图终止的代码支持的 any 方法。如果它不支持任何方法,那么他就不能使用任何方法。
  • 是的,很好,如果他不能更改函数的代码,即使只是添加对pthread_cleanup_push 的调用,我也看不出有什么办法。
  • 我已经在我的答案上做了一个注释,希望这能让它更清楚。
猜你喜欢
  • 2018-12-10
  • 2013-11-01
  • 2014-03-08
  • 2012-05-31
  • 1970-01-01
  • 2013-10-26
  • 2013-02-04
  • 1970-01-01
相关资源
最近更新 更多