2015-06-01 4 views
0

Я нашел ошибку в своей программе, что тот же поток проснулся дважды, воспользовавшись возможностью для запуска другого потока, тем самым вызывая непреднамеренное поведение. В моей программе требуется, чтобы все ожидания потоков выполнялись ровно один раз за ход. Эта ошибка возникает, потому что я использую семафоры, чтобы заставить потоки ждать. С помощью семафора, инициализированного счетчиком 0, каждый поток вызывает down семафору в начале его бесконечного цикла, а основной поток вызывает up в цикле for NThreads (количество потоков) раз. Иногда одна и та же нить принимает вызов up дважды, и проблема возникает.гарантирует пробуждение всех потоков и только один раз за каждый

Каков способ правильно справиться с этой проблемой? Использует ли переменные условия и трансляцию способ сделать это? Будет ли это гарантировать, что каждый поток пробуждается один раз и только один раз? Каковы другие хорошие возможности?

+0

Ваш вопрос кажется смутным для меня, но в целом да, переменные условия используются для проверки того, разрешено ли выполнение кода. – user2079303

+0

Я не верю, что переменные условий помогут вам сами, вы можете разбудить один поток или разбудить все потоки, но waker не может знать или контролировать, какой блокирующий поток будет разблокирован. К сожалению, я думаю, вам нужен один мьютекс для каждого потока, чтобы управлять состояниями следящего/блочного потока точно так, как вам нужно. – Segfault

+0

Проголосовать за то, что вы отметили c и C++, предотвращая любой нетривиальный ответ – kfsone

ответ

1

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

+0

Так просто и работает красиво! – xiver77

1

В окнах вы можете использовать WaitForMultipleObjects, чтобы выбрать готовый поток из потоков, которые не выполнялись в текущих итерациях Nthread.

Каждый поток должен иметь «готовое» событие для сигнала, когда оно будет готово, и событие «пробуждения», которое будет ждать после того, как оно сообщит о своем «готовом» событии.

В начале цикла основного потока (1-я итерация NThreads) вызовите WaitForMultipleObjects с массивом ваших «готовых» событий NThreads.

Затем установите событие «следящего» потока, соответствующее событию «ready», возвращенному WaitForMultipleObjects, и удалите его из массива «готовых» ручек. Это гарантирует, что поток, который уже запущен, не будет возвращен WaitForMultipleObjects на следующей итерации.

Повторите до последней итерации, где вы назовете WaitForMultipleObjects с массивом из 1 ручка потока (я думаю, что это будет работать так, как если бы вы вызвали WaitForSingleObject).

Затем повторно заполнить массив «готовых» событий NThreads для следующих новых итераций Nthreads.

Смежные вопросы