2008-09-16 3 views
20

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

Есть ли способ сделать неблокирующий pthread_join? Какое-то время поединка было бы неплохо.

что-то вроде этого:

 
foreach thread do 
    nb_pthread_join(); 
    if still running 
     pthread_cancel(); 

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

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

+1

неблокирующая нить соединяется? Я думал, что соединение связано с блокировкой: s – 2008-09-16 15:22:04

ответ

1

Как указывали другие, в стандартных библиотеках pthread нет неблокирующего pthread_join.

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

int killed_threads = 0; 
for(i = 0; i < num_threads; i++) { 
    int return = pthread_cancel(threads[i]); 
    if(return != ESRCH) 
     killed_threads++; 
} 
if(killed_threads) 
    printf("%d threads did not shutdown properly\n", killed_threads) 
else 
    printf("All threads exited successfully"); 

Там нет ничего плохого с вызовом pthread_cancel на все ваши нити (прекращено или нет), так называя, что для всех ваших потоков не будет блокировать и будет гарантировать нить выход (чистые или нет).

Это должно квалифицироваться как «простое» обходное решение.

+22

Этот ответ неверный. Успешно вызванное `pthread_cancel` на каждом потоке не гарантирует, что все потоки завершились. Возможно, они не достигли точки отмены, или даже если они есть, основной поток может быть запланирован первым и вернуться из `main`, убив процесс, прежде чем другие потоки смогут завершить очистку ... – 2011-07-07 03:32:35

0

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

1

Ответ действительно зависит от того, почему вы хотите это сделать. Например, если вы просто хотите очистить мертвые потоки, то, вероятно, проще всего использовать поток «мертвой нити», который петли и соединяется.

1

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

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

  • Тайм-аут происходит, или
  • Если условие выполнено.

Вы можете получить это в цикле и добавить еще некоторую информацию в свою логику. Лучший ресурс, который я нашел для этого, связанный с Pthreads, - это учебник: Программирование нитей POSIX (https://computing.llnl.gov/tutorials/pthreads/).

Я также очень удивлен, увидев, что нет API для приуроченного участия в Pthreads.

1

Там нет приуроченной pthread_join, но если вы ждете другого потока заблокирован на условиях, вы можете использовать приуроченную pthread_cond_timed_wait вместо pthread_cond_wait

2

Если вы разрабатываете для QNX, вы можете использовать функцию pthread_timedjoin().

В противном случае вы можете создать отдельный поток, который будет выполнять pthread_join(), и предупредить родительский поток, например, сигнализируя о семафоре, что дочерний поток завершен. Этот отдельный поток может возвращать то, что получает от pthread_join(), чтобы родительский поток определял не только когда ребенок завершает, но и какое значение он возвращает.

21

Если вы работаете приложения на Linux, вы можете быть заинтересованы, чтобы знать, что:

int pthread_tryjoin_np(pthread_t thread, void **retval); 

int pthread_timedjoin_np(pthread_t thread, void **retval, 
           const struct timespec *abstime); 

Будьте осторожны, так как суффикс предлагает это, «нп» означает «непереносимой». Они не являются стандартом POSIX, расширениями gnu, полезными.

link to man page

9

Механизм «pthread_join» является удобство использования, если это произойдет, чтобы делать то, что вы хотите. Он не делает ничего, что вы не могли бы сделать сами, и где это не совсем то, что вы хотите, код именно того, что вы хотите.

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

Начните с изменения мышления. Это не поток, который застревает, это то, что делал поток, который застревает.

+0

Добавьте пример кода, пожалуйста? У меня примерно такая же проблема, процесс вызывает два потока и должен выйти только после выхода потоков - ни один из ответов здесь не объяснил, как сделать что-то похожее на функцию wait() fork. (Я добавил этот вопрос в избранное, он уведомит меня, как только вы ответите автоматически) – 2012-01-10 23:37:36