2010-07-01 3 views
13

API-интерфейсы потоков Windows и Solaris позволяют создавать поток в «приостановленном» состоянии. Поток начинается только тогда, когда он «возобновляется». Я привык к потокам 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. 

The (проще) POSIX эквивалентно, как представляется:

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

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

+1

О, кстати, я понимаю, что использование CreateThread напрямую - это не то, что вы должны делать с C/C++ - это не дает C-Runtime возможность инициализировать различные вещи для домашнего хозяйства. _beginthreadex следует использовать вместо этого (или так я читаю.) – Ragster

+0

Реализация такого механизма на POSIX не составит труда. Вам нужно будет использовать простой pthread_cond_wait – adf88

+0

@Ragster - спасибо за подсказку. _beginthreadex() - действительно правильный способ запуска потока в Windows. –

ответ

22
  1. Чтобы перенаправить ресурсы, а затем начать практически сразу.
  2. У вас есть механизм, который повторно использует поток (возобновляет его), но у вас нет потока для повторного использования, и вы должны его создать.
+0

+1 это очень хорошие причины. – stinky472

+0

Оба этих ответа подразумевают, что для создания потока требуется дорого. В Google я обнаружил, что Windows и Linux занимают ~ 0.2 мс для создания потока. Это действительно дорого. –

+0

Повторяющееся несколько раз это может быть серьезной стоимостью. – adf88

8

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

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

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

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

Есть несколько примеров использования в Windows с помощью C/C++ (Richter/Nasarre), если вы хотите много деталей!

1

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

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

3

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

+0

Это говорит о том, что вам нужно, чтобы обойти недостатки в WinAPI. Все эти параметры для CreateThread() и вы * still * не можете создать нужный поток!

2

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

3

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

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

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

+0

pthreads не страдает от этой расы, так как идентификатор потока задается ссылкой. pthread_create() может гарантировать, что идентификатор потока установлен до начала потока. Интерфейс CreateThread() имеет эту проблему, поэтому я вижу, что может потребоваться «начать приостановку». –

+1

Хм, он также задан ссылкой в ​​CreateThread. Не знаете, что такое курица. –