Cobegin
Begin P1:= 1; while true do (* бесконечный цикл *) begin (* процесс А *) wait (P1); (* защищенный ресурс *) signal (P1); … end; (* процесс А *) while true do (* бесконечный цикл *) begin (* процесс В *) wait (Pl); (* защищенный ресурс *) signa l(Pl); … end;(* процесс В *) coend; end. (* sem_example *) Семафор гарантирует, что два процесса могут получить доступ к защищенному ресурсу только по очереди. При этом не создается никаких дополнительных связей - если один процесс исполняется быстрее другого, то за определенный промежуток времени он будет чаще получать доступ к ресурсу. Процесс вынужден ждать окончания другого только в том случае, когда последний находится в критической секции. Одновременно гарантируется и живучесть. Если исполнение процесса по каким-либо причинам прекращается, то, при условии, что он находился вне критической секции, это не мешает развитию другого процесса. Само по себе применение семафоров не гарантирует предотвращения тупиковых ситуаций. Если два процесса используют семафоры следующим образом wait (Pl) wait (P2) wait (P2) wait (Pl) … … (* защищенный ресурс *) (* защищенный ресурс *) … … signal (Pl) signa l(P2) signal (P2) signal (Pl) то по-прежнему существует риск возникновения тупика. Если переключение процессов происходит между двумя операторами wait первой программы, а вторая программа выполнит свои операторы wait, то это приводит к тупику, поскольку каждая программа ожидает от другой освобождения семафора. Проблема состоит в том, что, хотя семафор гарантирует неразрывность проверки и установки значения, он сам остается защищенным ресурсом. В приведенном примере явно нарушен запрет последовательного выделения, и это приводит к возможности тупиковых ситуаций. Семафор может помочь при синхронизации взаимосвязанных действий. Например, если процесс должен работать с данными только после того, как они считаны с внешнего порта, программа может иметь следующий вид: Process "Чтение данных" Process "Обработка данных"
|