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

hiz5n14c  于 2023-11-16  发布在  其他
关注(0)|答案(4)|浏览(190)

我有一个关于主线程和同一进程中其他线程的问题。当主函数返回时,其他线程也退出吗?我对此感到困惑。
考虑以下测试代码:

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;
}

字符串
当“main thread return.”打印出来时,线程test1和test2也退出了,谁能告诉我为什么?

bfnvny8b

bfnvny8b1#

当主线程返回时(即,您从main函数返回),它会终止整个进程。这包括所有其他线程。当您调用exit时也会发生同样的事情。您可以通过调用pthread_exit来避免这种情况。
pthread_detach的目的是让你不需要加入其他线程来释放它们的资源。分离一个线程并不能使它在进程终止后仍然存在,它仍然会和其他线程一起被销毁沿着。

m2xkgtsf

m2xkgtsf2#

您应该在每个新线程上使用pthread_join(),通知调用线程等待子线程,挂起执行-并退出进程-直到这些线程终止。
在创建的线程上调用pthread_detach不会在进程退出后保留它们。在Linux man page中:
detached属性仅仅决定线程终止时系统的行为;如果进程使用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函数。

w6lpcovy

w6lpcovy3#

main()返回时,进程中的所有线程都将终止。
libc库负责在main()函数返回时调用exit()来实现此行为。反过来,exit()函数将最终调用名为_exit()的精简 Package 器函数,(从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()函数。

chhkpiq4

chhkpiq44#

作为对同一主题的旁白,我想指出在我看来APUE第三版中的不准确之处在7.3节中,它说“正常终止有五种方式”,其中包括“调用pthread_exit(第11.5节)从最后一个线程”。在我看来,这是不正确的,因为main仍然在运行(并且pthread_exit不会终止程序,因为main会这样做)或者main已经返回,所以终止程序,正如本文正确指出的那样。

相关问题