Вопрос

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

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

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

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

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

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

Это было полезно?

Решение

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

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

Другие советы

Если вы запускаете свое приложение в 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, хотя и полезны.

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

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

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

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

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

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

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

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

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

  • Наступает тайм-аут, или
  • Если это условие будет выполнено.

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top