условная переменная - PullRequest
       15

условная переменная

8 голосов
/ 08 февраля 2009

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

Должен ли я использовать условную переменную pthread, чтобы разбудить поток, или есть более подходящий механизм?

Если я позвоню pthread_cond_signal(), когда другой поток не заблокирован pthread_cond_wait(), а скорее что-то делает, что произойдет? Будет ли потерян сигнал?

Ответы [ 5 ]

12 голосов
/ 08 февраля 2009

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

Самый простой и правильный способ сделать это заключается в следующем:

pthread_mutex_t queue_lock;
pthread_cond_t  not_empty;
queue_t queue;

push()
{
  pthread_mutex_lock(&queue_lock);
  queue.insert(new_job);
  pthread_cond_signal(&not_empty)
  pthread_mutex_unlock(&queue_lock);
}
pop()
{
  pthread_mutex_lock(&queue_lock);
  if(queue.empty()) 
     pthread_cond_wait(&queue_lock,&not_empty);
  job=quque.pop();
  pthread_mutex_unlock(&queue_lock);
}
11 голосов
/ 08 февраля 2009

Из руководства pthread_cond_signal :

Функции pthread_cond_broadcast () и pthread_cond_signal () не должны действовать, если в cond в настоящее время нет потоков, заблокированных.

Я предлагаю вам использовать Семафоры . По сути, каждый раз, когда задача вставляется в очередь, вы «поднимаете» семафор. Рабочий поток блокирует семафор, «опуская» его. Поскольку для каждой задачи он будет «активирован» один раз, рабочий поток будет работать до тех пор, пока в очереди есть задачи. Когда очередь пуста, семафор равен 0, и рабочий поток блокируется, пока не прибудет новая задача. Семафоры также легко справляются со случаем, когда более одного задания прибыло, когда рабочий был занят. Обратите внимание, что вам все еще нужно заблокировать доступ к очереди, чтобы сохранять / вставлять атомарные элементы.

1 голос
/ 02 сентября 2011

Сигнал будет потерян, но вы хотите, чтобы сигнал в этом случае был потерян. Если для пробуждения нет потока, сигнал не имеет смысла. (Если никто не ждет чего-то, никто не должен быть уведомлен, когда это происходит, верно?)

В случае условных переменных потерянные сигналы не могут привести к тому, что поток "спит в огне". Если вы на самом деле не кодируете поток, чтобы перейти в спящий режим, когда пожар уже есть, нет необходимости «сохранять сигнал». Когда начнется пожар, ваша трансляция разбудит все спящие темы. И вам придется быть довольно глупым, чтобы закодировать поток, чтобы заснуть, когда огонь уже есть.

0 голосов
/ 11 июня 2014

Нет эффектов.

Если вы проверите, как реализован pthread_condt_signal, condt использует несколько счетчиков, чтобы проверить, есть ли ожидающие потоки для пробуждения. например, glibc-nptl

 /* Are there any waiters to be woken?  */
 if (cond->__data.__total_seq > cond->__data.__wakeup_seq){
    ...
 }
0 голосов
/ 08 января 2013

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

В коде artyom было бы лучше заменить «if» на «while» в функции pop () для обработки ложного пробуждения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...