非阻塞pthread_join

问题描述 投票:0回答:9

我正在编码多线程服务器的关闭。如果一切顺利,所有线程都应该自行退出,但是线程被卡住的可能性很小。在这种情况下,使用非阻塞会很方便加入,这样我就可以做到。

有没有办法进行非阻塞pthread_join? 某种定时加入也不错。

类似这样的:

foreach 线程做
  nb_pthread_join();
    如果仍在运行
      pthread_cancel();

我可以想到更多非阻塞连接有用的情况。

似乎没有这样的函数,所以我已经编写了一个解决方法,但它并不像我想要的那么简单。

c multithreading pthreads
9个回答
28
投票

如果您在 Linux 上运行应用程序,您可能有兴趣了解:

int pthread_tryjoin_np(pthread_t thread, void **retval);

int pthread_timedjoin_np(pthread_t thread, void **retval,
                                const struct timespec *abstime);

请小心,正如后缀所示,“np”表示“不可移植”。它们不是 POSIX 标准、GNU 扩展,但很有用。

链接到手册页


9
投票

如果“pthread_join”机制恰好能满足您的要求,那么使用它会很方便。它不会做任何你自己做不到的事情,并且如果它不完全是你想要的,就准确地编写你想要的代码。

没有真正的理由你应该真正关心线程是否已终止。您关心的是线程正在执行的工作是否完成。为了说明这一点,让线程做一些事情来表明它正在工作。如何做到这一点取决于您的特定问题的理想选择,这在很大程度上取决于线程正在做什么。

从改变你的想法开始。并不是线程被卡住了,而是线程正在执行的操作被卡住了。


3
投票

如果您正在为 QNX 进行开发,则可以使用 pthread_timedjoin() 函数。

否则,您可以创建一个单独的线程来执行 pthread_join() 并通过信号量(例如,子线程已完成)发出信号来提醒父线程。这个单独的线程可以返回从 pthread_join() 获取的内容,以便让父线程不仅确定子线程何时完成,还确定它返回的值。


1
投票

正如其他人指出的那样,标准 pthread 库中没有可用的非阻塞 pthread_join。

但是,考虑到您所说的问题(试图保证所有线程在程序关闭时都退出),不需要这样的函数。 你可以简单地这样做:

int killed_threads = 0;
for(i = 0; i < num_threads; i++) {
   int return = pthread_cancel(threads[i]);
   if(return != ESRCH)
      killed_threads++;
}
if(killed_threads)
    printf("%d threads did not shutdown properly\n", killed_threads)
else
    printf("All threads exited successfully");

在所有线程(终止与否)上调用 pthread_cancel 没有任何问题,因此为所有线程调用 pthread_cancel 不会阻塞并保证线程退出(干净与否)。

这应该算是一个“简单”的解决方法。


1
投票

答案实际上取决于您为什么要这样做。例如,如果您只想清理死线程,那么最简单的方法可能就是使用一个循环和连接的“死线程清理器”线程。


1
投票

我不确定你到底是什么意思,但我假设你真正需要的是等待和通知机制。

简而言之,它的工作原理如下:等待条件满足并超时。如果满足以下条件,您的等待就会结束:

  • 发生超时,或者
  • 如果条件满足。

您可以将其循环起来,并为您的逻辑添加更多智能。我找到的与 Pthreads 相关的最佳资源是本教程: POSIX 线程编程 (https://computing.llnl.gov/tutorials/pthreads/)。

我也很惊讶地发现 Pthreads 中没有用于定时连接的 API。


1
投票

没有定时

pthread_join
,但是如果您正在等待其他线程在条件下被阻塞,您可以使用定时
pthread_cond_timed_wait
代替
pthread_cond_wait


0
投票

您可以将一个字节推入以非阻塞方式打开的管道中,以便在完成时向另一个线程发出信号,然后使用非阻塞读取来检查管道的状态。


0
投票

您可以使用 pthread_kill(thread_id, 0) 来检查线程是否存在。

// Non-blocking pthread_join. This returns EEXIST if the thread is
// still running.
int nb_pthread_join(pthread_t tid, void **status)
{
    if (pthread_kill(tid, 0) == 0) {
    return EEXIST;
    }
    return pthread_join(tid, status);
}
© www.soinside.com 2019 - 2024. All rights reserved.