Я кодирую завершение работы многопоточного сервера. Если все идет так, как должно, все потоки выходят сами по себе, но есть небольшая вероятность, что поток застрянет. В этом случае было бы удобно иметь неблокирующее соединение. так что я мог сделать.
Есть ли способ сделать pthread_join неблокирующим? Было бы неплохо и какое-то синхронизированное соединение.
что-то вроде этого:
foreach thread do
nb_pthread_join();
if still running
pthread_cancel();
Я могу подумать и о других случаях, когда неблокирующее соединение было бы полезно.
Похоже, такой функции нет, поэтому я уже написал обходной путь, но это не так просто, как хотелось бы.





Вы можете протолкнуть байт в канал, открытый как неблокирующий, чтобы сигнализировать другому потоку о его завершении, а затем использовать неблокирующее чтение для проверки состояния канала.
Ответ действительно зависит от того, почему вы хотите это сделать. Например, если вы просто хотите очистить мертвые потоки, вероятно, проще всего иметь поток «очистителя мертвых потоков», который зацикливается и соединяется.
Я не уверен, что именно вы имеете в виду, но предполагаю, что вам действительно нужен механизм ожидания и уведомления.
Вкратце, вот как это работает: вы ждете выполнения условия с таймаутом. Ваше ожидание закончится, если:
Вы можете сделать это в цикле и добавить больше интеллекта в вашу логику. Лучший ресурс, который я нашел для этого, связанный с Pthreads, - это этот учебник: Программирование потоков POSIX (https://computing.llnl.gov/tutorials/pthreads/).
Я также очень удивлен, увидев, что в Pthreads нет API для синхронизированного соединения.
Нет pthread_join с синхронизацией, но если вы ждете, что другой поток заблокирован по условиям, вы можете использовать pthread_cond_timed_wait с синхронизацией вместо pthread_cond_wait.
Если вы разрабатываете для QNX, вы можете использовать функцию pthread_timedjoin ().
В противном случае вы можете создать отдельный поток, который будет выполнять pthread_join () и предупреждать родительский поток, например, сигнализируя семафору о завершении дочернего потока. Этот отдельный поток может возвращать то, что получает от pthread_join (), чтобы родительский поток мог определять не только время завершения дочернего процесса, но и то, какое значение он возвращает.
Как отмечали другие, в стандартных библиотеках 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 для всех ваших потоков (завершенных или нет), поэтому вызов этого для всех ваших потоков не будет блокироваться и гарантирует выход потока (чистый или нет).
Это должно рассматриваться как «простой» обходной путь.
Это неверный ответ. Успешный вызов pthread_cancel в каждом потоке не гарантирует, что все потоки завершились. Возможно, они не достигли какой-либо точки отмены, или даже если они достигли, основной поток может быть запланирован первым и вернуться из main, убивая процесс, прежде чем другие потоки смогут завершить очистку ...
Я думаю, что для этого ответа требуется pthread_join () после pthread_cancel (): «После завершения отмененного потока соединение с этим потоком с использованием pthread_join (3) получает PTHREAD_CANCELED в качестве статуса выхода потока. (Присоединение к потоку - единственный способ чтобы знать, что отмена завершена.) "
Если вы запускаете свое приложение в 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 удобен, если он делает именно то, что вы хотите. Он не делает того, что вы не могли бы сделать сами, а там, где это не совсем то, что вы хотите, кодируйте именно то, что вы хотите.
Нет реальной причины, по которой вам действительно следует заботиться о том, завершился поток или нет. Что вас волнует, так это то, завершена ли работа, выполняемая потоком. Чтобы сказать это, попросите поток сделать что-нибудь, чтобы указать, что он работает. Как вы это сделаете, зависит от того, что идеально подходит для вашей конкретной проблемы, что во многом зависит от того, что делают потоки.
Начните с изменения своего мышления. Застрял не поток, а то, что он делал.
Добавьте, пожалуйста, образец кода? У меня примерно такая же проблема, процесс вызывает два потока и должен завершиться только после выхода потоков - ни один из ответов здесь не объяснял, как сделать что-то похожее на функцию fork (). (Я добавил этот вопрос в избранное, он сообщит мне, как только вы ответите автоматически)
Имейте логическое значение, защищенное мьютексом, в котором хранится статус того, что вы хотите знать. При желании используйте условную переменную, чтобы сигнализировать об изменении логического значения.
Спасибо. Пример кода был бы полезен, но я мог бы попробовать поискать и в другом месте.
Ваш вопрос просто "как мне чего-то ждать"?
Да; потоки posix (pthread_create и pthread_join), похоже, работает аналогично тому, что мне нужно, используя pthread_join ... теперь нет проблем. Спасибо за уделенное время.
... ... или нет. Как я уже сказал, пример кода был бы полезен, они, кажется, просто выполняют успешный вызов pthread_join, но поток не завершает свою работу.
@gry Вместо того, чтобы пытаться присоединиться к потоку, дождитесь завершения задания. Это сводит ваш вопрос к гораздо более простому - «как мне чего-то ждать». Ответ: используйте условные переменные.
Какую функцию мне следует использовать для работы с условными переменными? У вас есть справочная страница, название функции, пример, к которому можно обратиться? (как упоминалось ранее, я добавил этот вопрос в избранное, он сообщит мне, как только вы ответите автоматически)
неблокирующее присоединение к потоку? Я думал, что присоединение связано с блокировкой: s