Неблокирующая pthread_join - PullRequest
       19

Неблокирующая pthread_join

21 голосов
/ 16 сентября 2008

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

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

как то так:

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

Я могу подумать, что больше случаев, когда неблокирующее объединение было бы полезно.

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

Ответы [ 8 ]

22 голосов
/ 07 августа 2009

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

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

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

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

ссылка на справочную страницу

10 голосов
/ 24 сентября 2011

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

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

Начните с изменения вашего мышления. Застревает не нить, а то, чем занимался нить.

2 голосов
/ 17 сентября 2008

Как отмечали другие, в стандартных библиотеках 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 во всех ваших потоках (прерванных или нет), поэтому вызов, который для всех ваших потоков не заблокирует и гарантирует выход из потока (чистый или нет).

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

2 голосов
/ 17 сентября 2008

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

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

1 голос
/ 17 сентября 2008

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

1 голос
/ 16 сентября 2008

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

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

  • Время ожидания истекло или
  • Если условие выполнено.

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

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

1 голос
/ 16 сентября 2008

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

0 голосов
/ 16 сентября 2008

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

...