Гарантировано ли, что pthread_cond_signal пробудит ожидающий поток?

Это общий вопрос. Например, в настоящее время два дочерних потока называются pthread_cond_wait(&cond1,&mutex), и они оба ждут. Затем родительский поток вызывает

pthread_cond_signal(&cond1);
pthread_cond_signal(&cond1);

Далее, мой вопрос: гарантировано ли, что оба из двух ожидающих потоков будут разбужены? (Предположим, что первый поток разбудил выпуски mutex позже на определенном этапе выполнения, чтобы второй поток мог его получить).

Причина, по которой я задаю этот вопрос, заключается в том, что для сигнала уровня системы unix сигнал (скажем, SIGCHLD) не поставлен в очередь, так что несколько сигналов одного типа могут быть потеряны, если они будут доставлены последовательно. Поэтому я удивляюсь, что pthread_cond_signal реализован по-разному, так что они не потеряются, если планировщик будет пропускать сигнал родительского потока дважды подряд?

Ответ 1

Быстрый ответ:

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

Из здесь:

Вызов pthread_cond_signal() разблокирует хотя бы один из потоков которые блокируются при заданной переменной условия cond (если есть потоки блокируются на cond).

Вызов pthread_cond_broadcast() блокирует все потоки в настоящее время заблокирован при заданной переменной условия cond.

Более длинный ответ:

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

Однако я не знаю, так ли это для вашей конкретной реализации pthread или нет (и на данный момент сайт glibc довольно хитроумный, поэтому не может получить доступ к коду, который нужно посмотреть).

Ответ, возможно, еще не реализованный, но-он-в-спецификации:

Следует отметить, однако, что спецификация недавно немного изменилась в отношении того, как pthread_cond_signal() и pthread_cond_broadcast() определяют, какие потоки фактически блокируются при заданной переменной условия, но я полагаю, что не все реализации до сих пор догнали.

Длинную дискуссию по этому вопросу можно найти здесь, с новой спецификацией:

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

Итак, вывод: Не являясь экспертным интерпретатором спецификаций, я бы сказал, что новый текст поддерживает предположение об этом синхронно - чтобы два последовательных вызова pthread_cond_signal() с двумя доступными доступными потоками, пробуждали оба потока.

Я не уверен на это на 100%, поэтому, если кто-то может разработать, не стесняйтесь это делать.

Ответ 2

Я знаю, что это старый поток (каламбур не предназначен), но типичные реализации работают следующим образом:

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

Блокировка будет иметь очередь потоков, которые были усыплены, потому что они пытались ее получить, но она удерживалась другим потоком.

cond_wait добавляет текущий поток в очередь переменных состояния, освобождает блокировку и помещает себя в режим сна.

cond_signal просто перемещает один спящий поток из очереди переменной условия в очередь блокировки.

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

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