Штатным способом разблокирования потока, блокированного на условной переменной, является вызов функции, сигнализирующей о выполнении условия. В native API это функция
SyncCondvarSignal()
, которая имеет две POSIX-обертки:
pthread_cond_signal()
и
pthread_cond_broadcast()
. Разница между ними заключается в том, что первая пробуждает только один, самый приоритетный поток из ждущих выполнения условия, а вторая пробуждает все потоки, ожидающие выполнения условия.
Однако необходимо помнить про специфику ожидания внутри критической секции: вызов функции
pthread_cond_broadcast()
только переведет ожидающие потоки из состояния блокирования на условной переменной в состояние блокировки на мьютексе, поскольку мьютекс сможет захватить только самый приоритетный поток.
Нештатным способом завершения ожидания на условной переменной может быть приход немаскированного сигнала UNIX. Если для данного сигнала определен обработчик, он выполнится без захвата мьютекса, а попытка захвата будет произведена уже после его завершения.
int pthread_cond_signal(pthread_cond_t* cond);
Функция переводит в состояние готовности самый приоритетный поток из блокированных на условной переменной
cond
, после чего поток предпринимает попытку захвата своего мьютекса. Если есть несколько потоков с равным (и высшим) приоритетом, блокированных на условной переменной, то разблокируется тот поток, который ожидал дольше остальных.
Возвращаемые значения:
EOK
— успешное завершение;
EFAULT
— произошла ошибка при попытке обращения к указателям
cond
или
mutex
;
EINVAL
— не инициализирована переменная, на которую указывает
cond
.
int pthread_cond_broadcast(pthread_cond_t* cond);
Вызов функции разблокирует все потоки, блокированные на условной переменной
cond
. Потоки разблокируются в порядке приоритетов. Для потоков равного приоритета разблокирование проводится в порядке FIFO.
Возвращаемые значения:
EOK
— успешное завершение;
EFAULT
— произошла ошибка при попытке обращения к указателям
cond
или
mutex
;
EINVAL
— не инициализирована переменная, на которую указывает
cond
.
int pthread_cond_destroy(pthread_cond_t* cond);
Вызов функции деинициализирует условную переменную
cond
. Для дальнейшего использования условной переменной, на которую ссылается
cond
, ее необходимо инициализировать вызовом
pthread_cond_init()
. Функция может использоваться для изменения параметров условной переменной.
Возвращаемые значения:
EOK
— успешное завершение;
EBUSY
— в данный момент другой поток блокирован на условной переменной
cond
;
EINVAL
— не инициализирована переменная
cond
.
QNX предоставляет упрощенный вариант использования условной переменной для блокирования (остановки) потока при помощи интерфейса так называемой
За этим интерфейсом на самом деле скрывается один мьютекс и несколько дополнительных условных переменных. Использование функций ожидания должно проходить внутри участка кода, отмеченного вызовами блокирования и разблокирования мьютекса, ассоциированного со ждущей блокировкой. Одним из основных недостатков ждущей блокировки является то, что для всех потоков и всех ключей ожидания используется один общий мьютекс. ОС не может никоим образом отслеживать взаимные блокировки потоков при использовании ждущих блокировок. В целом поведение этого средства синхронизации идентично бинарным семафорам, но оно требует дополнительных операций блокирования мьютекса.
Все функции для работы со ждущими блокировками объявлены в файле
.
Вызов функций ожидания может производиться только внутри блока захвата и освобождения ждущей блокировки:
int pthread_sleepon_lock(void);
int pthread_sleepon_unlock(void);
Функция захвата
pthread_sleepon_lock()
возвращает следующие значения:
EOK
— успешное выполнение;
EDEADLK
— попытка повторного захвата мьютекса;
EAGAIN
— может возникнуть при первом вызове в процессе, если системе не хватает ресурсов для создания внутреннего мьютекса.
Функция освобождения
pthread_sleepon_unlock()
возвращает значения:
EOK
— успешное выполнение;