Мы инициализируем семафор значением 1. Вызвав sem_wait, мы ожидаем, когда значение семафора окажется больше 0, а затем уменьшаем его на 1. Вызов sem_post увеличивает значение с 0 до 1 и возобновляет выполнение всех потоков, заблокированных в вызове sem_wait для данного семафора. Хотя семафоры и могут использоваться в качестве взаимных исключений, они обладают некоторыми особенностями: взаимное исключение должно быть разблокировано именно тем потоком, который его заблокировал, в то время как увеличение значения семафора может быть выполнено другим потоком. Можно привести пример использования этой особенности для решения упрощенной версии задачи потребителей и производителей из главы 7 с двумя бинарными семафорами. На рис. 10.3 приведена схема с одним производителем, помещающим объект в общий буфер, и одним потребителем, изымающим его оттуда. Для простоты предположим, что в буфер помещается ровно один объект. Рис. 10.3. Задача производителя и потребителя с общим буфером В листинге 10.2 приведен текст соответствующей программы на псевдокоде.Листинг 10.1. Сравнение бинарных семафоров и взаимных исключений
инициализация взаимного исключения; инициализация семафора единицей;
pthread_mutex_lock(&mutex); sem_wait(&sem);
критическая область критическая область
pthread_mutex_unlock(&mutex); sem_post(&sem);