2009-11-12 5 views
2

Я работаю над приложением для Linux в C, которое использует несколько потоков. Нити, которые генерируются основной функцией, выполняют большую часть работы, и поэтому обычно заканчиваются последним. Я вижу какое-то странное поведение, и я считаю, что это связано с тем, что основной поток заканчивается до того, как порожденные потоки смогут закончить работу. Вот некоторые примеры кода, чтобы проиллюстрировать то, что я говорю:проблема завершения нити (c программирование)

#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; 
} 

Когда этот код выполняется, сообщение из функции очистки печатается дважды, как это должно быть, но в других случаях, когда он запускается, я см. сообщение, напечатанное только один раз, и в других случаях я вижу его напечатанным три раза или совсем нет. Вы добавляете функцию сна в основную функцию, чтобы играть с тем, сколько времени требуется для завершения основной функции.

Что я могу сделать, чтобы программа работала так, как должна? Я подозреваю, что это связано с присоединением к детям, но я не совсем понимаю концепцию объединения или как применить его к этой ситуации.

Заранее благодарен!

+0

Это дубликат http://stackoverflow.com/questions/1695106/multiple-threads-in-c-program и http://stackoverflow.com/ Вопросы/1680224/posix-threads-problem - Я бы положил хорошие деньги, это самый часто задаваемый вопрос pthreads (даже если собеседник иногда не знает, что это вопрос, который они задают!) – caf

ответ

3

Да, вы должны «присоединиться» к нитям. «Соединение» потока просто означает ожидание окончания потока. Другими словами, вы бы сделали

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

Ожидать, пока оба потока не прекратятся.

Редактировать: Что делать, если у вас есть дочерний поток, который, в свою очередь, создает поток «внука»? Как правило, тот, кто создал поток, должен дождаться его завершения («присоединить» его). Таким образом, в этом случае дочерний поток вызовет phtread_join в потоке grandchild, а основной поток вызовет join в дочернем потоке.

+0

Спасибо! мне нужно присоединиться ко всем тем, которые я создаю? что, если у меня есть поток, который создает поток? как я могу присоединиться к этой теме? – Carl

+0

@ Карл: Я отредактировал свой ответ, чтобы обсудить этот случай. –

+0

Обратите внимание, что если вы не собираетесь использовать 'pthread_join', вы также можете использовать' pthread_detatch', чтобы устранить утечку памяти, которую вы имели бы в противном случае. Однако вы не будете знать, когда поток прекратится. – bdonlan

2

Я думаю, что вы хотите запустить pthread_join на каждом из потоков, когда ваш основной поток завершен - это заставляет основной поток останавливаться, пока данный поток не закончит работу. Другие потоки все еще могут выполнить сначала, хотя, поэтому запуск pthread_join в каждом потоке будет препятствовать завершению основного потока до тех пор, пока все остальные не прекратятся.

1

Существует определенная проблема, если main() заканчивается перед потоками, которые он породил, если вы не вызываете pthread_exit() явно. Все созданные им потоки прекратятся, потому что 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

Смежные вопросы