【问题标题】:When the main thread exits, do other threads also exit?当主线程退出时,其他线程是否也退出?
【发布时间】:2012-08-06 05:43:03
【问题描述】:

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

考虑以下测试代码:

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

【问题讨论】:

  • 问题文本与问题正文不匹配。这是关于主线程退出时发生的事情吗?或者这是关于当主线程从main 函数返回时会发生什么? (显然,如果线程退出,则无法返回。它可以做一个或另一个。)

标签: c multithreading pthreads


【解决方案1】:

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

在创建的线程上调用pthread_detach不会在进程退出后保留它们。来自linuxman 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 函数。

【讨论】:

  • 仔细阅读pthread_detach 的文档。它不像你想象的那样做。
  • @laifjei 也许您误认为分离与提供的功能 e。 G。在 Java/C#/Python/等中。 - 守护线程。 Java 在内部保持进程处于活动状态,而任何非守护线程保持活动状态(即使主线程死亡)。
【解决方案2】:

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

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

【讨论】:

  • 这个答案是不正确的。当主线程(或任何线程)调用exit,或者main的初始调用返回时,整个进程退出。但是主线程可以用pthread_exit退出而不影响其他线程。
  • @R.. 是不是表示一个进程可以退出,但它的线程继续执行?
  • @hsalimi:进程退出后线程无法继续。 R 表示主线程可以通过pthread_exit 退出而其他线程继续。
  • @hsalimi:不。线程是进程的一部分。如果进程退出,它们(连同所有其他进程资源)将不复存在。通过pthread_exit 终止初始线程不会导致进程退出。
【解决方案3】:

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

libc 库负责通过在 main() 函数返回时调用 exit() 来实现此行为。反过来,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() 函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-07
    • 1970-01-01
    • 2014-03-17
    • 1970-01-01
    相关资源
    最近更新 更多