Заставить основную программу ждать завершения потоков

В следующем коде я создаю несколько потоков, и каждый поток засыпает в течение нескольких секунд.

Однако моя основная программа не дожидалась завершения потоков, я был в предположении, что потоки продолжат работать, пока они не закончат сами.

Есть ли способ сделать потоки продолженными, даже если вызывающий поток заканчивается.

#include <pthread.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>


int sample(int min,int max){
  int r=rand();
  return (r %max+min );
}



void *worker(void *p){
  long i = (long) p;
  int s = sample(1,10);
  fprintf(stdout,"\tid:%ld  will sleep: %d \n",i,s);
  sleep(s);
  fprintf(stdout,"\tid:%ld  done sleeping \n",i,s);
}

pthread_t thread1;

int main(){
  int nThreads = sample(1,10);

  for(int i=0;i<nThreads;i++){
    fprintf(stderr,"\t-> Creating: %d of %d\n",i,nThreads);
    int iret1 = pthread_create( &thread1, NULL, worker, (void*) i);
    pthread_detach(thread1);
  }
  //  sleep(10);//work if this is not commented out.
  return 0;
}

Спасибо

Edit:

Извините, что не уточнил, возможно ли это без явного отслеживания текущих текущих потоков и с помощью объединения.

Ответ 1

Каждая программа имеет основной поток. Это поток, в котором выполняется ваша функция main(). Когда выполнение этого потока завершается, программа заканчивается вместе со всеми ее потоками. Если вы хотите, чтобы ваш основной поток ожидал других потоков, используйте pthread_join function

Ответ 2

Вам нужно следить за потоками. Вы не делаете этого, потому что используете одну и ту же переменную thread1 для каждого потока, который вы создаете.

Вы отслеживаете потоки, создавая список (или массив) типов pthread_t, которые вы передаете функции pthread_create(). Затем вы pthread_join() те потоки в списке.

изменить:

Хорошо, вам на самом деле лениво не следить за запуском потоков. Но вы можете выполнить то, что хотите, имея глобальный var (защищенный мьютексом), который увеличивается до момента завершения потока. Затем в основной теме вы можете проверить, получает ли этот var значение, которое вы хотите. Скажите nThreads в своем примере кода.

Ответ 3

Вам нужно присоединиться к каждой создаваемой теме:

int main()
{
    int                    nThreads = sample(1,10);
    std::vector<pthread_t> threads(nThreads);

    for(i=0; i<nThreads; i++)
    {
            pthread_create( &threads[i], NULL, worker, (void*) i)
    }

    /* Wait on the other threads */
    for(i=0; i<nThreads; i++)
    {
            status*   status;
            pthread_join(threads[i], &status);
    }
}

Ответ 4

Вы поняли, что ваше предположение было неправильным. Главная особенность. Выход из главного будет убивать ваши потоки. Таким образом, есть два варианта:

  • Используйте pthread_exit для выхода из основного. Эта функция позволит вам выйти из основного, но сохранить другие потоки.

  • Сделайте что-нибудь, чтобы сохранить живое. Это может быть любое из цикла (глупо и неэффективно) для любого блокирующего вызова. pthread_join является обычным явлением, поскольку он блокирует, но также дает вам статус возврата потоков, если вы заинтересованы, и очищайте ресурсы мертвых потоков. Но в целях сохранения основной функции от завершения любого блокирующего вызова будет действовать, например. выбирать, читать канал, блокировать семафор и т.д.

Так как Мартин показал join(), здесь pthread_exit():

int main(){
  int nThreads = sample(1,10);

  for(int i=0;i<nThreads;i++){
    fprintf(stderr,"\t-> Creating: %d of %d\n",i,nThreads);
    int iret1 = pthread_create( &thread1, NULL, worker, (void*) i);
    pthread_detach(thread1);
  }

  pthread_exit(NULL);
}