【问题标题】:thread termination issue (c programming)线程终止问题(c 编程)
【发布时间】:2010-12-16 01:48:16
【问题描述】:

我正在开发一个使用多线程的 C 语言 Linux 应用程序。由 main 函数产生的线程完成了大部分工作,因此通常最后完成。我看到一些奇怪的行为,我相信这是由于主线程在生成的线程有机会完成它们的工作之前终止。下面是一些示例代码来说明我在说什么:

#define _POSIX_C_SOURCE 200112L
#define _ISOC99_SOURCE
#define __EXTENSIONS__
#define _GNU_SOURCE

#include <pthread.h>
#include <stdio.h>

void
my_cleanup(void *arg)
{
     printf("cleanup: %s\n", (char *)arg);
}


void *
thread_stuff(void *arg)
{
     printf("thread started\n");
     pthread_cleanup_push(cleanup, "running");
     if (arg)
          pthread_exit((void *)2);
     pthread_cleanup_pop(0);
     pthread_exit((void *)2);
}


int
main()
{
     int err;
     pthread_t tid1, tid2;

     err = pthread_create(&tid1, NULL, thread_stuff, (void *)1);
     err = pthread_create(&tid2, NULL, thread_stuff, (void *)1);

     sleep(10);                 /* change the value here if you want */

     return SUCCESS;
}

运行此代码时,清理功能的消息按应有的方式打印两次,但在其他时候运行时,我有时只看到消息打印一次,而其他时候我看到它打印了 3 次或者根本没有。在 main 函数中添加 sleep 函数来玩一下 main 函数终止需要多长时间。

我可以做些什么来让程序正常运行?我怀疑它与加入孩子有关,但我不完全理解加入的概念或如何将其应用于这种情况。

提前致谢!

【问题讨论】:

标签: c multithreading join posix pthreads


【解决方案1】:

是的,您应该“加入”这些线程。 “加入”线程只是意味着等待线程终止。换句话说,你会这样做

pthread_join(tid1, NULL);
pthread_join(tid2, NULL);

等到两个线程都终止。

编辑:如果您有一个子线程,而该子线程又创建了一个“孙子”线程,该怎么办?通常,创建线程的人都应该等待它终止(“加入”它)。所以在这种情况下,子线程会在孙线程上调用 phtread_join,而主线程会在子线程上调用 join。

【讨论】:

  • 谢谢!我需要加入我创建的所有线程吗?如果我有一个创建线程的线程怎么办?我如何加入这个“孙子”线程?
  • 请注意,如果您不打算使用pthread_join,您也可以使用pthread_detatch 来消除否则会出现的内存泄漏。但是,您将不知道线程何时终止。
  • OP 的代码中没有内存泄漏,因为它正在退出,而是过早退出。 pthread_detach 对此无济于事,但从 main 调用 pthread_exit 而不是返回会起作用...
【解决方案2】:

我认为您想在主线程完成时在每个线程上运行pthread_join - 这会使主线程停止,直到给定线程完成运行。不过其他线程仍然可以先完成,因此在每个线程上运行 pthread_join 将阻止主线程终止,直到所有其他线程都终止。

【讨论】:

    【解决方案3】:

    如果你没有显式调用 pthread_exit(),那么如果 main() 在它产生的线程之前完成,就会出现一个明确的问题。它创建的所有线程都将终止,因为 main() 已完成并且不再存在以支持线程。

    通过让 main() 显式调用 pthread_exit() 作为它所做的最后一件事,main() 将阻塞并保持活动状态以支持它创建的线程,直到它们完成。

    int main()
        {
             int err;
             pthread_t tid1, tid2;
    
             err = pthread_create(&tid1, NULL, thread_stuff, (void *)1);
             err = pthread_create(&tid2, NULL, thread_stuff, (void *)1);
    
             sleep(10);                 /* change the value here if you want */
    
             /* Add the pthread_exit */     
             pthread_exit(NULL);
             return SUCCESS;
        }
    

    更多信息请参考here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-02
      • 2015-11-22
      • 1970-01-01
      • 1970-01-01
      • 2011-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多