Во-первых, здесь нет проблемы правильности.Любой заказ будет работать.Вспомните, что всякий раз, когда вы используете условные переменные, вы должны зацикливаться на предикате во время ожидания:
pthread_mutex_lock(mutex);
while (!predicate)
pthread_cond_wait(cvar);
pthread_mutex_unlock(mutex);
Сигнализируя после разблокировки, вы не вносите никаких проблем с корректностью;поток по-прежнему гарантированно активируется, и в худшем случае сначала происходит другое пробуждение - в этот момент он видит, что предикат становится истинным и продолжает работу.
Однако возможны две проблемы с производительностью.
- «Спешите и подождите».По сути, если вы подаете сигнал, пока блокировка удерживается, другому потоку все еще нужно ждать, пока мьютекс не станет доступен.Многие реализации pthreads вместо пробуждения другого потока просто перемещают его в очередь ожидания мьютекса, сохраняя ненужный цикл wakeup-> wait.В некоторых случаях, однако, это не реализовано или недоступно, что приводит к потенциальному ложному переключению контекста или IPI.
Ложные пробуждения.Если вы дадите сигнал после разблокировки, другой поток сможет выполнить другое пробуждение.Рассмотрим следующий сценарий:
- Поток A начинает ожидать добавления элементов в потокобезопасную очередь.
- Поток B вставляет элемент в очередь.После разблокировки очереди, но до того, как он выдает сигнал, происходит переключение контекста.
- Поток C вставляет элемент в очередь и выдает сигнал cvar.
- Поток A пробуждается иобрабатывает оба элемента.Затем он возвращается к ожиданию в очереди.
- Поток B возобновляет работу и сигнализирует cvar.
- Поток A просыпается, а затем немедленно возвращается в спящий режим, поскольку очередь пуста.
Как вы можете видеть, это может привести к ложному пробуждению, которое может потратить некоторое время процессора.
Лично я не думаю, что это тоже стоит беспокоитьсямного об этом в любом случае.Вы не часто сами знаете, поддерживает ли ваша реализация перемещение официантов из переменной условия в очередь ожидания мьютекса, что является единственным реальным критерием, который вы можете использовать, чтобы решить, какой из них использовать.если бы мне пришлось выбирать, сигнализация после разблокировки незначительно реже может привести к неэффективности, поскольку неэффективность требует гонки с тремя потоками, а не гонки с двумя потоками для «поторопись и жди»" состояние.Однако об этом не стоит беспокоиться, если тесты не показывают слишком много издержек переключения контекста или что-то в этом роде.