Стивенс Уильям Ричард
Шрифт:
При первом вызове sem_post значение семафора изменилось с –2 на –1 и один из процессов, ожидавших изменения значения семафора, был разблокирован.
Выполним те же действия в Solaris 2.6, обращая внимание на различия в реализации:
Аналогично очередям сообщений Posix файлы создаются в каталоге /tmp, причем указываемое при вызове имя становится суффиксом имен файлов. Разрешения первого файла соответствуют указанным в вызове sem_open, а второй файл, как можно предположить, используется для блокировки доступа.
Проверим, что ядро не осуществляет автоматического увеличения значения семафора при завершении работы процесса, установившего блокировку:
Посмотрим теперь, как меняется значение семафора в этой реализации при появлении новых процессов, ожидающих изменения значения семафора:
Можно заметить отличие по сравнению с результатами выполнения той же последовательности команд в Digital Unix 4.0B: после изменения значения семафора управление сразу же передается ожидающему изменения семафора процессу.
10.6. Задача производителей и потребителей
В разделе 7.3 мы описали суть задачи производителей и потребителей и привели несколько возможных ее решений, в которых несколько потоков-производителей заполняли массив, который обрабатывался одним потоком-потребителем.
1. В нашем первом варианте решения (раздел 7.2) потребитель запускался только после завершения работы производителей, поэтому мы могли решить проблему синхронизации, используя единственное взаимное исключение для синхронизации производителей.
2. В следующем варианте решения (раздел 7.5) потребитель запускался до завершения работы производителей, поэтому требовалось использование взаимного исключения (для синхронизации производителей) вместе с условной переменной и еще одним взаимным исключением (для синхронизации потребителя с производителями).
Расширим постановку задачи производителей и потребителей, используя общий буфер в качестве циклического: заполнив последнее поле, производитель (buff[NBUFF-1]) возвращается к его началу и заполняет первое поле (buff[0]), и потребитель действует таким же образом. Возникает еще одно требование к синхронизации: потребитель не должен опережать производителя. Мы все еще предполагаем, что производитель и потребитель представляют собой отдельные потоки одного процесса, но они также могут быть и просто отдельными процессами, если мы сможем создать для них общий буфер (например, используя разделяемую память, часть 4).