何时使用pthread_exit()以及何时在Linux中使用pthread_join()?

dex*_*ous 42 c linux pthreads

我是pthreads的新手,我正在努力理解它.我看到了一些如下例子.

我可以看到它main()被API阻止了pthread_exit(),我已经看到了主要功能被API阻止的示例pthread_join().我无法理解何时使用什么?

我指的是以下网站 - https://computing.llnl.gov/tutorials/pthreads/.我无法获得何时使用pthread_join()以及何时使用的概念pthread_exit().

有人可以解释一下吗?此外,pthreads的良好教程链接将不胜感激.

#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS     5

void *PrintHello(void *threadid)
{
   long tid;
   tid = (long)threadid;
   printf("Hello World! It's me, thread #%ld!\n", tid);
   pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int rc;
   long t;
   for(t=0; t<NUM_THREADS; t++){
      printf("In main: creating thread %ld\n", t);
      rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
      if (rc){
         printf("ERROR; return code from pthread_create() is %d\n", rc);
         exit(-1);
      }
   }

   /* Last thing that main() should do */
   pthread_exit(NULL);
Run Code Online (Sandbox Code Playgroud)

实现了一件事,即

pthread_cancel(thread);
pthread_join(thread, NULL);
Run Code Online (Sandbox Code Playgroud)

有时,您希望在执行时取消该线程.你可以使用pthread_cancel(thread);来完成这个.但是,请记住,您需要启用pthread取消支持.此外,取消时清理代码.

thread_cleanup_push(my_thread_cleanup_handler, resources);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);

static void my_thread_cleanup_handler(void *arg)
{
  // free
  // close, fclose
}
Run Code Online (Sandbox Code Playgroud)

Suv*_*yil 40

正如openpub文档中所解释的那样,

pthread_exit() 将退出调用它的线程.

在你的情况下,主要调用它,主线程将终止,而你的衍生线程将继续执行.这主要用于主线程只需要生成线程并让线程完成其工作的情况

pthread_join 除非目标线程终止,否则将暂停执行已调用它的线程

这在您想要在主线程中进一步处理之前等待thread/s终止的情况下非常有用.

  • 也许自从您回答这个问题后,实现就发生了变化。根据 dexterous 网站的说法,通过让 main() 显式调用 pthread_exit() 作为它所做的最后一件事,main 将阻塞并保持活动状态以支持它创建的线程,直到它们完成。也就是说,线程不能存在于主线程 main() 之外。 (2认同)

Alo*_*ave 13

pthread_exit终止调用线程,同时pthread_join暂停执行调用线程,直到目标线程完成执行.

在开放组文档中详细解释了它们:

  • 但是你在main()中看到了,我调用了pthread_exit().这阻止了main()的终止,并使线程运行并完成.这样,它与pthread_join()非常相似.此外,pthread_join()阻止main()的终止,直到并且除非执行该线程. (2认同)

Jen*_*edt 8

这两种方法都可确保您的进程在所有线程结束之前不会结束.

join方法使您的main函数线程显式等待所有要"加入"的线程.

pthread_exit方法main以受控方式终止您的函数和线程.main具有特殊性,main否则将终止您的整个过程,包括所有其他线程.

为此,您必须确保没有任何线程正在使用在其main函数内声明的局部变量.这种方法的优点是你main不必知道你的进程中已经启动的所有线程,例如因为其他线程自己创建了新的线程main而不知道任何事情.

  • @SHREYASJOSHI,不,它没有阻止`main`功能.`main`函数的*thread*将被终止.看起来你的混乱是`main`函数,它的执行线程和重组*all*线程的进程.`main`函数有两种特殊的方式:它是启动进程的*first*线程,如果它以`return`或`exit`结束,则终止整个进程.但是如果你用`pthread_exit`结束它,那个线程就会结束而其他线程仍然存在. (2认同)

小智 5

pthread_exit() API

如前所述,用于调用线程终止。调用该函数后,将启动复杂的清理机制。当它完成时,线程终止。当 pthread_create() 创建的线程中发生对 return() 例程的调用时,也会隐式调用 pthread_exit() API。实际上,调用 return() 和调用 pthread_exit() 具有相同的影响,都是从 pthread_create() 创建的线程调用的。

区分初始线程(在 main() 函数启动时隐式创建)和 pthread_create() 创建的线程非常重要。从 main() 函数调用 return() 例程会隐式调用 exit() 系统调用,并且整个过程终止。没有启动线程清理机制。从 main() 函数调用 pthread_exit() 会导致清理机制启动,当它完成其工作时,初始线程终止。

当从 main() 函数调用 pthread_exit() 时,整个进程(以及其他线程)会发生什么取决于 PTHREAD 实现。例如,在 IBM OS/400 实现上,当从 main() 函数调用 pthread_exit() 时,整个进程包括其他线程都将终止。其他系统的行为可能有所不同。在大多数现代 Linux 机器上,从初始线程调用 pthread_exit() 不会终止整个进程,直到所有线程终止。 如果您想编写可移植的应用程序,请小心使用 main() 中的 pthread_exit()。

pthread_join() API

是一种等待线程终止的便捷方式。您可以编写自己的等待线程终止的函数,这可能更适合您的应用程序,而不是使用 pthread_join()。例如,它可以是一个基于等待条件变量的函数。

我建议阅读David R. Butenhof的书“使用 POSIX 线程编程”。 它很好地解释了所讨论的主题(以及更复杂的事情)(尽管一些实现细节,例如 main 函数中的 pthread_exit 用法,并不总是反映在书中)。