我怎么能等待任何/所有pthreads完成?

Bra*_*rad 34 c linux multithreading pthreads posix-api

我只是希望我的主线程在退出之前等待任何和所有我的(p)线程完成.

由于不同的原因,线程出现了很多,我真的不想跟踪所有这些 - 我只是想知道它们什么时候都消失了.

wait()为子进程执行此操作,在没有子进程时返回ECHILD,但是等待(似乎没有)(p)线程.

我真的不想经历保存每个未完成线程列表的麻烦(因为它们来来去去),然后必须在每个线程上调用pthread_join.

有一个快速而肮脏的方法来做到这一点?

Mic*_*urr 26

所有线程完成后,您是否希望主线程特别做任何事情?

如果没有,您可以简单地调用主线程pthread_exit()而不是返回(或调用exit()).

如果main()返回它隐式调用(或行为就好像它被调用)exit(),这将终止进程.但是,如果main()调用pthread_exit()而不是返回,exit()则不会发生该隐式调用,并且该进程不会立即结束 - 它将在所有线程终止时结束.

不能太快,更脏.

这是一个小例子程序,可以让你看到差异.传递-DUSE_PTHREAD_EXIT给编译器以查看进程等待所有线程完成.在没有定义宏的情况下进行编译,以查看进程在其轨道中停止线程.

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

static
void sleep(int ms)
{
    struct timespec waittime;

    waittime.tv_sec = (ms / 1000);
    ms = ms % 1000;
    waittime.tv_nsec = ms * 1000 * 1000;

    nanosleep( &waittime, NULL);
}

void* threadfunc( void* c)
{
    int id = (int) c;
    int i = 0;

    for (i = 0 ; i < 12; ++i) {
        printf( "thread %d, iteration %d\n", id, i);
        sleep(10);
    }

    return 0;
}


int main()
{
    int i = 4;

    for (; i; --i) {
        pthread_t* tcb = malloc( sizeof(*tcb));

        pthread_create( tcb, NULL, threadfunc, (void*) i);
    }

    sleep(40);

#ifdef USE_PTHREAD_EXIT
    pthread_exit(0);
#endif

    return 0;
}
Run Code Online (Sandbox Code Playgroud)


gra*_*ron 23

正确的方法是跟踪你所有的pthread_id,但你要求一个快速而肮脏的方式,所以在这里.基本上:

  • 只保留运行线程的总数,
  • 在调用pthread_create之前在主循环中递增它,
  • 每个线程完成时减少线程数.
  • 然后在主进程结束时休眠,直到计数返回0.

.

volatile int running_threads = 0;
pthread_mutex_t running_mutex = PTHREAD_MUTEX_INITIALIZER;

void * threadStart()
{
   // do the thread work
   pthread_mutex_lock(&running_mutex);
   running_threads--;
   pthread_mutex_unlock(&running_mutex);
}

int main()
{
  for (i = 0; i < num_threads;i++)
  {
     pthread_mutex_lock(&running_mutex);
     running_threads++;
     pthread_mutex_unlock(&running_mutex);
     // launch thread

  }

  while (running_threads > 0)
  {
     sleep(1);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 使用屏障而不是计数器和互斥锁可以更容易地实现这一点. (3认同)
  • 这些操作绝对不是原子的.互斥是必不可少的.查看障碍; 它们更容易使用并为您计数. (2认同)