Необходима ли pthread_yield() при ожидании pthread_join()?

В следующем коде необходимо вызывать pthread_yield() в основном потоке, когда он блокируется в ожидании pthread_join() ?

void *myThread(void *result)
{
   //do something here
   return 0;
}

int main()
{
   pthread_t tid;
   void *status = 0;
   int result;

   pthread_create(&tid, NULL, myThread, &result);
   
   // do I need pthread_yield() here?
   
   pthread_join(tid, &status);

   return 0;
}

Если нет, то каков допустимый вариант использования pthread_yield()? В большинстве основных случаев, которые я могу придумать, ОС/планировщик уже автоматически обрабатывает это.

Не не надо. Как вы думаете, почему это может быть необходимо? Помогает ли это: stackoverflow.com/a/65381133/898348?

Jabberwocky 18.04.2023 11:59

Уступка нити не была необходима в этом столетии.

user207421 18.04.2023 12:05

@Jabberwocky Спасибо, я тоже так подозреваю, просто хочу перепроверить

cuckoo 18.04.2023 12:36

@user207421, какой век тут ни при чем. Никогда не существовало реализации pthreads, в которой вызов pthread_yield() был бы полезен в этот момент.

Solomon Slow 18.04.2023 12:48
pthread_yield()больше даже не существует в POSIX
Andrew Henle 18.04.2023 13:12

@SolomonSlow Вы говорите конкретно о pthreads. Я говорю о потоке в целом.

user207421 18.04.2023 13:33

@ user207421, вызывающий абонент спрашивает конкретно о программе, которая вызывает pthread_create, pthread_join и, возможно, pthread_yield. Было бы трудно дать осмысленный ответ, не относящийся к библиотеке pthreads. Но ладно, скажем, это вопрос конкретно о pthread_join, и давайте спросим «нужна ли мне какая-либо уступка потока» перед вызовом pthread_join? Ответ по-прежнему таков: нет. Никогда не было времени, когда любая уступка была бы выгодна непосредственно перед вызовом pthread_join.

Solomon Slow 18.04.2023 15:33

Я бы сказал, что pthread_join() не является необходимым и является едва ли не худшим из возможных способов использования нескольких потоков.

Martin James 18.04.2023 16:11

@MartinJames Можете ли вы рассказать об этом подробнее?

cuckoo 18.04.2023 16:21

@MartinJames, вызов pthread_join() из основного потока предотвращает возврат main() до того, как целевой поток завершит свою работу. Libc вызовет exit и завершит весь процесс, если main() будет разрешено просто вернуться. Кроме того, либо вызов соединения, либо pthread_detach необходимы, если сам процесс будет продолжать работать в течение неопределенного времени после завершения потока. Поток, который не был ни отсоединен, ни присоединен, станет «зомби», который будет продолжать удерживать внутрипроцессные и общесистемные ресурсы после своего завершения. man7.org/linux/man-pages/man3/pthread_join.3.html

Solomon Slow 18.04.2023 16:23
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
10
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

... нужно ли вызывать pthread_yield() в основном потоке, когда он блокируется в ожидании pthread_join()?

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

каков допустимый вариант использования pthread_yield()?

Отредактировано (Извинения всем, кто уже проголосовал за этот вопрос.)

Больше нет вариантов использования pthread_yield(). Теперь он устарел в Linux и никогда официально не входил в библиотеку pthreads.† Не следует писать новый код, который вызывает устаревшие функции.

Но некоторые операционные системы поддерживают вызов «выход» (например, sched_yield(), который появляется как в Linux и в спецификации UNIX.) Вызов «выход» позволяет потоку сказать: «Я хочу, чтобы мой квант времени закончить сейчас». Одним из вариантов использования может быть уступка в узком цикле опроса. Это то, что вы редко увидите в коде, который работает как обычное приложение в ОС общего назначения, потому что ОС предоставляет системные вызовы программы, которые могут ожидать практически любого события; но вы можете увидеть это в коде какого-нибудь встроенного приложения реального времени.


† Спасибо Эндрю Хенле, чей комментарий к первоначальному вопросу предупредил меня об этом факте.

Спин-блокировки пользовательского пространства являются примером, где полезны yields или sleep(0). Хотя вы можете возразить, что спин-блокировки пользовательского пространства — плохая идея, и точка.

doron 18.04.2023 14:46

@doron, Могли бы поспорить? Я возражал против использования спин-блокировок пользовательского пространства в крупном коммерческом продукте, но доктор компьютерных наук, отвечавший за системную архитектуру, остановил меня. Его точка зрения заключалась в том, что вероятность того, что любые два потока действительно столкнутся на одной из спин-блокировок, была практически нулевой, и что время, сэкономленное за счет спин-блокировки вместо использования мьютекса, стоило риска возможного столкновения. Я сомневался, что неоспоримый мьютекс стоит так дорого, но у меня не было ресурсов, чтобы фактически измерить производительность в реальных условиях.

Solomon Slow 18.04.2023 16:05

Linux использует системные вызовы futex (и futex2) для блокировки мьютекса). Если мьютекс не оспаривается (как и должно быть в 99,9% случаев в производительном коде), вызовы ядра вообще не выполняются (обновляются только атомарные переменные)

doron 18.04.2023 16:18

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