Почему я хотел бы запустить “приостановленный” поток?

API потока Windows и Соляриса оба позволяют потоку быть созданным в "приостановленном" состоянии. Поток только на самом деле запускается, когда он позже "возобновляется". Я привык к потокам POSIX, которые не имеют этого понятия, и я изо всех сил пытаюсь понять мотивацию для него. Кто-либо может предложить, почему было бы полезно создать "приостановленный" поток?

Вот простой иллюстративный пример. WinAPI позволяет мне делать это:

t = CreateThread(NULL,0,func,NULL,CREATE_SUSPENDED,NULL);
// A. Thread not running, so do... something here?
ResumeThread(t);
// B. Thread running, so do something else.

(Более простой) эквивалентный POSIX, кажется:

// A. Thread not running, so do... something here?
pthread_create(&t,NULL,func,NULL);
// B. Thread running, so do something else.

У кого-либо есть какие-либо реальные примеры, где они смогли сделать что-то в точке (между CreateThread & ResumeThread), который был бы трудным на POSIX?

14
задан alex tingle 1 July 2010 в 10:17
поделиться

6 ответов

  1. Для предварительного выделения ресурсов и последующего почти немедленного запуска потока.
  2. У вас есть механизм, который повторно использует поток (возобновляет его), но на самом деле у вас нет потока для повторного использования, и вы должны его создать.
22
ответ дан 1 December 2019 в 06:47
поделиться

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

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

Другой пример может быть для случая, когда вы хотите использовать пул потоков - вы заранее создаете необходимые потоки, приостанавливаете их, а затем, когда поступает запрос, выбираете один из потоков, устанавливаете информацию о потоке для задачи и затем установите его как планируемое.

Осмелюсь сказать, что есть способы обойтись без CREATE_SUSPENDED, но он определенно имеет свое применение.

Есть несколько примеров использования в «Windows через C / C ++» (Richter / Nasarre), если вам нужно много деталей!

9
ответ дан 1 December 2019 в 06:47
поделиться

В CreateThread существует неявное условие гонки: вы не можете получить ID потока до , после поток не начал работать. Когда вызов возвращается, это совершенно непредсказуемо, поскольку все, что вы знаете, поток, возможно, уже завершился. Если поток вызывает какое-либо взаимодействие в остальной части этого процесса, для которого требуется TID, значит, у вас проблема.

Это не является неразрешимой проблемой, если API не поддерживает запуск потока приостановленным, просто поместите блок потока на мьютекс сразу и освободите этот мьютекс после возврата из вызова CreateThread.

Однако есть еще одно использование CREATE_SUSPENDED в Windows API, с которым очень трудно справиться, если поддержка API отсутствует. Вызов CreateProcess () также принимает этот флаг, он приостанавливает поток запуска процесса. Механизм идентичен, процесс загружается, и вы получаете PID, но код не запускается, пока вы не отпустите поток запуска. Это очень полезно, я использовал эту функцию для настройки защиты процесса, которая обнаруживает сбой процесса и создает минидамп. Флаг CREATE_SUSPEND позволял мне обнаруживать и обрабатывать сбои инициализации, которые обычно очень трудно устранить.

4
ответ дан 1 December 2019 в 06:47
поделиться

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

3
ответ дан 1 December 2019 в 06:47
поделиться

Однажды я столкнулся с похожей проблемой. Причины приостановки исходного состояния рассматриваются в другом ответе.

Мое решение с pthread заключалось в использовании мьютекса и cond_wait , но я не знаю, хорошее ли это решение и может ли оно покрыть все возможные потребности. Более того, я не знаю, можно ли считать поток приостановленным (в то время я считал слово «заблокированный» в руководстве синонимом, но, вероятно, это не так)

1
ответ дан 1 December 2019 в 06:47
поделиться

Используемые нами потоки могут обмениваться сообщениями, и у нас есть произвольно настраиваемые очереди сообщений с наследуемым приоритетом (описанные в файле конфигурации), которые соединяют эти потоки. Пока каждая очередь не будет построена и подключена к каждому потоку, мы не можем позволить потокам выполняться, поскольку они начнут отправлять сообщения в никуда и ожидать ответов. Пока не будет создан каждый поток, мы не можем создавать очереди, поскольку они должны к чему-то подключаться. Таким образом, ни одному потоку нельзя разрешить выполнять работу, пока не будет настроен самый последний поток. Мы используем boost.threads, и первое, что они делают, - это ждут boost :: барьер .

3
ответ дан 1 December 2019 в 06:47
поделиться