Сигнализация между потоками

Дизайн приложения

У меня есть приложение C ++, которое имеет поток производителя, несколько очередей (созданных во время выполнения) и потребительский поток.

Поток источника получает данные через Tcp / Ip и помещает их в соответствующую очередь (например, если данные относятся к типу A и помещаются в очередь A).

Поток потребителя в настоящий момент перебирает очереди от 1 до n для обработки данных из каждой очереди.

В соответствии с требованием нет необходимости отслеживать очередь, которая в последний раз обновлялась или меньше всего. Пока обновляется любая очередь, потребитель должен обрабатывать от 1 до n очередей.

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

Синхронизация ресурсов и сигнализация между потоками:

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

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

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

Выпуск:

Давайте возьмем этот сценарий и рассмотрим, как потребитель обрабатывает данные n-й очереди; в то же время производитель может поместить данные в очередь n-1, n-2, и сигнализация не эффективна, поскольку потребитель не спит и обрабатывает n-ые данные. Как только потребитель завершит обработку данных n-й очереди, он будет находиться в спящем режиме, и данные в n-1, n-2 не будут обрабатываться до тех пор, пока слушатель не выдаст какой-либо дополнительный сигнал.

Как мы можем решить этот сценарий?
Люди также советуют использовать семофор. Относится ли семафор к этому сценарию?

Заранее спасибо.

0

Решение

Это классический пример для C ++ 11 std::condition_variable.

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

3

Другие решения

Семафор подойдет, да.

Но я не совсем уверен, если это даже необходимо. Похоже, что ваша проблема вызвана исключительно тем, что потребительский поток не может вернуться назад после обработки очереди N. Он должен перейти в спящий режим только после того, как увидит N пустой очереди в очереди, удерживая мьютекс, чтобы гарантировать, что в это время записи не были добавлены.

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

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

1

Ты можешь использовать select и ждать с ним дескриптора файла, сделанного из сигнала ->, чтобы он мог ждать по тайм-ауту (у select есть они) и просыпаться при получении сигнала (сигнал должен быть замаскирован & заблокирован). когда signalfd (смотреть man signalfd) читается, вы можете прочитать с него struct signalfd_siginfo и проверить ssi_signo для номера сигнала (если это тот, который вы используете для связи).

0
По вопросам рекламы [email protected]