27

我对同一进程中的主线程和其他线程有疑问。当主函数返回时,其他线程是否也退出?我对此感到困惑。

考虑以下测试代码:

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也退出了,谁能告诉我为什么?

4

3 回答 3

29

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

在进程退出后,调用pthread_detach创建的线程不会保留它们。从 linux手册页

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

您有时会看到使用pthread_exitinmain而不是显式pthread_join调用,其意图是以main这种方式退出将允许其他线程继续运行。事实上,linux 手册页明确说明了这一点:

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

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

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

于 2012-08-09T02:31:21.813 回答
24

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

的目的pthread_detach是为了让你不需要加入其他线程来释放它们的资源。分离一个线程不会使其在进程终止后存在,它仍然会与所有其他线程一起被销毁。

于 2012-08-09T02:41:00.810 回答
1

当您从main().

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

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

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

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's__libc_start_main()函数。

于 2021-07-15T16:09:10.950 回答