Синхронизация процессов.
Не смотря на то, что ресурсы можно разделять, они обычно доступны в каждый момент только одному процессу. Ресурс, который допускает обслуживание только одного пользователя за один раз, называется критическим ресурсом.
Если несколько процессов хотят использовать критический ресурс в режиме разделения времени, им следует синхронизировать свои действия таким образом, чтобы этот ресурс всегда находился в распоряжении не более, чем одного из них.
Если ресурс занят, то остальные процессы, которым он нужен, временно получают отказ и должны ждать, пока он не освободиться.
Внутри каждого процесса можно выделить места, в которых происходит обращение к критическим ресурсам. Эти места называются критическими участками.
Рассмотрим два независимых процесса:
Parbegin
Процесс_1: do while (true)
Begin
Критический участок 1;
end;
Оставшаяся часть процесса 1;
end;
Процесс_2: do while (true)
Begin
Критический участок 2;
end;
Оставшаяся часть процесса 2;
end;
Конструкция вида:
Parbegin
Оператор 1;
Оператор 1;
...
Оператор 1;
parend.
Означает, что операторы 1¸N выполняются параллельно.
Кстати, записи, приведенные выше, называются записями на псевдокоде.
Критические участки процессов соответствуют тем группам операция, которые обращаются к разделяемому критическому ресурсу.
Чтобы не допустить одновременного выполнения обоих критических участков, в системе должен быть предусмотрен механизм, который бы синхронизировал эти два процесса. Этот механизм должен обладать двумя свойствами:
1. Если один или несколько процессов хотят обратиться к своим критическим участкам, то один из них должен получить разрешение войти в свой критический участок.
2. В каждый момент времени не более, чем одному процессу разрешается находиться в своем критическом участке.
У процессов возникает не только проблема синхронизации, но и необходимость в обмене информацией.
Назовем словом “поставщик” процесс, который отправляет порции информации другому процессу, который назовем “потребитель”.
Эти порции информации можно рассматривать как сообщения.
Один из методов, применяемых при реализации передачи сообщений, состоит в том, что заводит пул свободных буферов, каждый из которых может содержать одно сообщение.
Между процессами Поставщик и Потребитель имеется очередь заполненных буферов, содержащих сообщение. Когда Поставщик хочет послать сообщение, он добавляет в хвост этой очереди еще один буфер. Потребитель, что бы получить сообщение, забирает из очереди буфер, который стоит в ее начале.
Такая организация требует, чтобы Поставщик и Потребитель кооперировались во многих областях. Они должны следить за количеством заполненных и свободных буферов. Поставщик может передавать сообщение только до тех пор, пока имеются свободные буфера. Потребитель может получать сообщения только, если очередь не пуста.
Для учета заполненных и свободных буферов нужны разделяемые переменные. Но раз переменные используются в режиме разделения, то потребуется и критические участки. Следовательно, изменять значение счетчика заполненных буферов следует в режиме взаимного исключения.
Та же проблема возникает при реализацииочереди сообщений. Пусть очередь реализована в виде связного списка. Если Поставщик добавляет сообщение в очередь как раз в тот момент, когда Потребитель забирает из нее самое последнее сообщение, может получиться неправильная ссылка в списке.
Такие процессы как Поставщик и Потребитель, общающиеся на равных правах, называются и сопрограммами. К сожалению, в литературе этому термину дается очень много различных определений. Чтобы избежать путаницы мы вместо него будем пользоваться термином “кооперирующиеся процессы”.
Если процессу Поставщик важно знать, что его сообщение получено, то Потребитель должен подтверждать получение каждого сообщения, т.е. Поставщик и Потребитель поменяются местами.
Если в системе имеется несколько пар “Поставщик – Потребитель”, то можно организовать разделение свободных буферов, объединив их общий пул.
Остановимся на решении проблем синхронизации и отношений типа “Поставщик – Потребитель”.
Дата добавления: 2016-06-15; просмотров: 1813;