你如何查询一个pthread,看看它是否仍在运行?

在我的析构函数中,我想干净地破坏一个线程。

我的目标是等待一个线程完成执行,然后破坏线程。

我发现查询pthread的唯一情况是pthread_attr_setdetachstate,但是这只能告诉你,如果你的线程是:

  • PTHREAD_CREATE_DETACHED
  • PTHREAD_CREATE_JOINABLE

这两者与线程是否仍在运行无关。

你如何查询一个pthread,看看它是否仍在运行?

听起来你在这里有两个问题:

我怎么才能等到我的线程完成?

回答:这是pthreads直接支持的 – 让你的线程停止JOINABLE(当它是第一次启动的时候),并且使用pthread_join()来阻塞你当前的线程,直到停止的线程不再运行。


我怎么知道我的线程是否还在运行?

答:你可以添加一个“thread_complete”标志来实现这个技巧:

场景:线程A想知道线程B是否还活着。

当创build线程B时,会给它一个指向“thread_complete”标志地址的指针。 在线程创build之前,“thread_complete”标志应该被初始化为NOT_COMPLETED。 线程B的入口点函数应立即调用pthread_cleanup_push()来推送一个“清理处理程序”,它将“thread_complete”标志设置为COMPLETED。

有关清理处理程序的详细信息,请参阅: pthread清理处理程序

你需要包含一个相应的pthread_cleanup_pop(1)调用,以确保清理处理程序被调用,无论是什么(即如果线程退出正常或由于取消等)。

然后,线程A可以简单地检查“thread_complete”标志来查看线程B是否退出。

注意:你的“thread_complete”标志应该被声明为“volatile”,并且应该是一个primefacestypes – GNU编译器为此提供了sig_atomic_t。 这允许两个线程一致访问相同的数据,而不需要同步结构(互斥/信号量)。

pthread_kill(tid, 0); 

没有信号发送,但错误检查仍然执行,所以你可以使用它来检查存在的tid。

小心 :此答案不正确。 该标准明确禁止传递一个终止线程的ID。 这个ID现在可能指定了一个不同的线程,或者更糟糕的是,它可能指向已被释放的内存,导致崩溃。

我想你真正需要的是调用pthread_join()。 这个调用在线程退出之前不会返回。

如果你只是想查询线程是否仍在运行(注意通常不是你应该做的!),你可以在线程退出之前设置一个volatile布尔值为false。那么你的主线程可以读取布尔值,如果它仍然是真的,你知道线程仍在运行。 (如果它是假的,另一方面,你知道这个线程至less几乎没有了;但是它可能仍然在运行清理代码,虽然它将布尔值设置为false,所以即使在这种情况下,你仍然应该调用pthread_join试图释放线程可能访问的任何资源)

没有完全可移植的解决scheme,请查看您的平台是否支持pthread_tryjoin_np或pthread_timedjoin_np。 所以你只要检查线程是否可以join(当然是用PTHREAD_CREATE_JOINABLE创build的)。

让我留意一下“获胜”的答案,这个答案有一个巨大的隐藏缺陷,在某些情况下会导致崩溃。 除非你使用pthread_join,否​​则它会一次又一次地出现。 假设你有一个进程和一个共享库。 调用库lib.so.

  1. 你把它打开,你开始一个线程。 假设你不想join它,所以你把它设置成可拆卸的。
  2. 进程和共享库的逻辑在做其工作等等…
  3. 你想装载lib.so,因为你不需要它了。
  4. 你调用线程的closures,然后你说,你想从你的lib.so的线程读取一个标志,它已经完成了。
  5. 你继续在dlclose的另一个线程,因为你看到,你已经看到,国旗现在显示线程“完成”
  6. dlclose会将所有堆栈和代码相关的内存加载出来。
  7. 但是,dlclose不会停止线程。 而且你知道,即使当你在清理处理程序的最后一行设置“线程已完成”的volatileprimefaces标志variables时,你仍然需要从堆栈中的很多方法返回,返回值等。一个巨大的线程优先#5 +#6的线程,你会收到dlclose才可以真正停止线程。 有时你会有一些不错的崩溃。

让我指出,这不是一个好的问题,我们的项目也有同样的问题。

 #include <string.h> #include <stdio.h> #include <pthread.h> #include <signal.h> #include <unistd.h> void* thread1 (void* arg); void* thread2 (void* arg); int main() { pthread_t thr_id; pthread_create(&thr_id, NULL, thread1, NULL); sleep(10); } void* thread1 (void* arg) { pthread_t thr_id = 0; pthread_create(&thr_id, NULL, thread2, NULL); sleep(5); int ret = 0; if( (ret = pthread_kill(thr_id, 0)) == 0) { printf("still running\n"); pthread_join(thr_id, NULL); } else { printf("RIP Thread = %d\n",ret); } } void* thread2 (void* arg) { // sleep(5); printf("I am done\n"); }