当主线程退出时,其他线程也会退出吗?

时间:2012-08-09 02:28:33

标签: c multithreading pthreads

我遇到了同一进程中主线程和其他线程的问题。当main函数返回时,其他线程也会退出吗?我对此感到困惑。

考虑以下测试代码:

void* test1(void *arg)
{
    unsigned int i = 0;
    while (1){
        i+=1;
    }
    return NULL;
}

void* test2(void *arg)
{
    long double i = 1.0;
    while (1){
        i *= 1.1;
    }
    return NULL;
}

void startThread ( void * (*run)(void*), void *arg) {
  pthread_t t;
  pthread_attr_t attr;
  if (pthread_attr_init(&attr) != 0
      || pthread_create(&t, &attr, run, arg) != 0
      || pthread_attr_destroy(&attr) != 0
      || pthread_detach(t) != 0) {
    printf("Unable to launch a thread\n");
    exit(1);
  }
}

int main()
{
    startThread(test1, NULL);
    startThread(test2, NULL);

    sleep(4);
    printf("main thread return.\n");

    return 0;
}

当"主线程返回时。"打印出来,线程test1和test2也退出,任何人都可以告诉我为什么?

3 个答案:

答案 0 :(得分:25)

您应该在每个新线程上使用pthread_join(),以通知调用线程在子线程上等待,暂停执行 - 并处理退出 - 直到这些线程终止。

在创建的主题上调用pthread_detach将不会在进程退出后保留它们。来自linux man page

  

分离属性仅在线程终止时确定系统的行为;如果进程使用exit(3)终止(或等效地,如果主线程返回),它不会阻止线程被终止。

您有时会在main中看到pthread_exit而非显式pthread_join次调用,目的是以这种方式退出main将允许其他线程继续运行。实际上,linux man page明确说明了这一点:

  

要允许其他线程继续执行,主线程应该通过调用pthread_exit()而不是exit(3)来终止。

但我不知道这是否是所有平台上的预期行为,而且我一直坚持使用pthread_join

pthread_join需要pthread_t作为目标线程,因此您的代码需要更改一点,因为您需要在调用pthread_join之前创建两个线程以等待它们。所以你不能在startThread中调用它。您需要返回pthread_t,或将pthread_t指针传递给startThread函数。

答案 1 :(得分:11)

当主线程返回时(即,从main函数返回),它将终止整个过程。这包括所有其他线程。当你致电exit时会发生同样的事情。您可以通过拨打pthread_exit来避免这种情况。

pthread_detach的目的是使它不需要与其他线程连接以释放其资源。分离线程不会使它在过程终止后存在,它仍然会与所有其他线程一起被销毁。

答案 2 :(得分:0)

当您从 main() 返回时,您进程中的所有线程都将终止。

libc 库负责通过在 exit() 函数返回时调用 main() 来实现此行为。反过来,exit() 函数将最终调用名为 _exit() 的瘦包装器函数(从 libc v2.3 开始)最终将调用 exit_group 系统调用和结束您的进程并终止其所有线程。

最后一个系统调用负责您注意到的行为。

我们可以在 _exit() 手册 here 中看到这个微妙的注释:

C library/kernel differences
       In glibc up to version 2.3, the _exit() wrapper function invoked
       the kernel system call of the same name.  Since glibc 2.3, the
       wrapper function invokes exit_group(2), in order to terminate all
       of the threads in a process.

如果您打算避免这种行为,唯一的选择是调用 pthread_exit,这将结束您的主线程并阻止您返回到 libc__libc_start_main() 函数。