Одним из вариантов использования условных переменных, который немного сложнее, чем просто очередь сообщений, является «разделение блокировки», когда разные потоки ожидают слегка разных условий одной и той же базовой природы. Например, у вас есть (очень тонкий, упрощенный) веб-кеш. Каждая запись в кеше имеет три возможных состояния: нет, IN_PROGRESS, COMPLETE.
getURL:
lock the cache
three cases for the key:
not present:
add it (IN_PROGRESS)
release the lock
fetch the URL
take the lock
update to COMPLETE and store the data
broadcast the condition variable
goto COMPLETE
COMPLETE:
release the lock and return the data
IN_PROGRESS:
while (still IN_PROGRESS):
wait on the condition variable
goto COMPLETE
Я на практике использовал шаблон для реализации варианта функции POSIX pthread_once
без помощи планировщика. Причина, по которой я не смог использовать семафор или блокировку для once_control
, а просто выполнить инициализацию под блокировкой, заключается в том, что функция не имела права на сбой, а once_control
имела только тривиальную инициализацию. В этом отношении, pthread_once
сам по себе не имеет определенных кодов ошибок, поэтому реализация его, возможно, не удастся, не оставляет вашего звонящего с хорошими вариантами ...
Конечно, с этим шаблоном вы должны быть осторожны с масштабированием. Каждый раз, когда завершается любая инициализация, каждый ожидающий поток просыпается, чтобы захватить блокировку. Поэтому, когда вы проектируете систему, вы очень внимательно относитесь к шардингу, а затем решаете, что вам не стоит беспокоиться о том, чтобы что-то реально реализовать, пока не увидите проверенные проблемы с производительностью.