В. Столлингс - Операционные системы (1114679), страница 51
Текст из файла (страница 51)
В каждом из процессов перед входом в кр -Ритический раздел выполняется вызов ~а1~ (э) . Если значение э становится отрицательным, процесс приостанавливается. Если же значение равно 1, оно уменьшается до нуля и процесс немедленно входит в критический раздел; по~~ольку э больше не является положительным, ни один другой процесс не моясет войти в критический раздел. Листинг 5.7. Взанмонсключения с использованием семафоров /* Програьаха еэаимьтого исключения */ соттэт.
1гтв гт =,/* Количество процессов Бегпарг!о2.е Б = 1 г тга1с( Р ', 1г 1 1 ) Семафор инициализируется значением 1. Следовательно, первый процесс, ~полняющий инструкцию матт., сможет немедленно попасть в критический Устанавливая при этом значение семафора равным О. Любой другой про- ц сс при попытке войти в критический раздел обнаружит, что он занят. Соответ- отвен произойдет блокировка процесса, а значение семафора будет уменьшено до -1 гт Пытаться войти в критический раздел может любое количество процессов; квжд, ттеуспешная попытка уменьшает значение семафора. После того как Процесс вошедший в критический раздел первым, покидает его, э увеличивает- ся, и „ о~ин из заблокированных процессов (если таковые имеются) удаляется из сааза„„ ""ой с семафором очереди и активизируется.
Таким образом, как только Р Шик операционной системы предоставит ему возможность выполнения, ц сс тут же сможет войти в критический раздел. процесс а Рттс. 5.3 показана возможная последовательность действий трех процеспт тт использовании технологии взаимоисключений, представленной в лис- о- Параллельные вычисления: взаимоисключения... Кр!!тический развел Обычное выволнеииа .,'. «» иа1'с (1оск) ! ! ! Обычный код иозкет в процессаии параллельно; критические разделы— только ло очереди ийз.1е (зп <= спс) ~* Бездействие */; ы = Ь(соГ); сиса н) потребление и*/ /» Орсизвсдствс зз'.емеита и Ь(з.п) = чз ~с+!т «" ъ'ага ().ос)с) ! 1 ! ! ! -3» ай..а' ()оса) - «в;:дпа1(1осХ) - " «'в1йт.а1 (1осК) Лрииечание Занятая часть б)в()ара зааприкоаана Рис. 5.4.
Бесконечный буфер задачи производитель~потребитель Часть 2. П „е 5.7. В этом примере три процесса (А, В, С) обращаются к разде рсу, защищенному семафором Хсс)с. Процесс А выполняет ыаз.ь (1с, ' зьку в этот момент семафор имеет значение 1, процесс А может не ги в критический раздел и значение семафора становится равным О,, злится в критическом разделе, и В, и С выполняют операцию иаз.г., и '. з заблокированном состоянии ожидают доступности критического процесс А покидает критический раздел и выполняет о)(г' ) () сс)с), процесс В (являющийся первым в очереди) получает гь войти в критический раздел. "ис.
5.3. Доступ процессов к разделяемым данным, защищенным семафорсоа ! Программа, приведенная в листинге 6.7, может так же хорошо рабо случае, когда одновременно в критическом разделе находятся нес зессов. Для этого достаточно инициализировать семафор соответст гением, Следовательно, в любой момент времени значение з. соипь и тется следующим образом. з. сспт!с > О. "значение э. сснпл определяет количество процессов, ка могут выполнить !чазт. (з) без приостановки процесса (подразумева промежуточные вызовы э~~па).
(з) отсутствуют). ,;.ссит!г. < О. абсолютное значение з.ссспг. определяет количество приос- тановленных процессов и очереди з . ~!зеь!е. дадяча производителятпотребителя Сейчас мы РассмотРим однУ из обЩих задач паРаллельных вычислений— дачу производителя!'потребителя. Вот ее обобщенная формулировка. Имеются ин или несколько производителей, генерирующих данные некоторого типа п)тси, символы и т.п.) и помещающих их в буфер, а также единственный поебитель, который извлекает помещенные в буфер элементы по одному.
Требугся затцитить систему от перекрытия операций с буфером, т.е. обеспечить, чтоодновременно получить доступ к буферу мог только один процесс !производитель или потребитель). Мы рассмотрим несколько решений этой задачи, с тем чтобы проиллюстрировать как мощь семафоров, так и встречающиеся при их использовании ловушки. для начала предположим„что буфер бесконечен и представляет собой линейный массив элементов. Говоря абстрактно, мы можем определить функции производителя и потребителя следующим образом: Ороиэесдитель */ ,т» потребитель *т' и)!х)е(скпв) !чсдп 1 е ( Ь кое ) На рис.
5.4 показана структура буфера Ь. Производитель может генерировать данные и сохранять их в буфере со своей индивидуальной скоростью. Всякий Раз при сохранении увеличивается индекс з.п. Потребитель поступает аналогично, с тем отличием, что он не должен считывать данные из пустого буфера. Следовательно, перед выполнением считывания он должен убедиться, что производитель обогнал его (зп > с!!г).
Цоп пытаемся реализовать нашу систему с использованием бинарных семафо* лист , асами * истинге б.8 приведена первая попытка реализации. Вместо работы с ини зп и сис мы можем просто отслеживать количество элементов в буфере ~ Параллальиые вычисления: взаимоисклшчеиия... и 4. и«агу зепар)~оге Б = 1) азату зетарйоге ое1ау = 01 ргос)осег() ыМ1е(гасе) ( рх ос)Псе ( ); иа1гВ(з); арреио(); и++" 1Х (и == 1) аудиа1Б(бе1ау) з1оиа1В(з); Потребитель Производитель э п ие1ау 1 0 О 0 0 0 3 и++ 4 11 ( и==1 ) а 1Виа 1В МЕ1ау).'-- 5 а10~ а1В (а) О 1 О 0 1 1 ха1(.В(з)' саМ() ' з1оиа1В (з); сопзлте (): 1й (и == О) иа1СБ(с)е1ау); 1 1 1 1 1 0 жа1сВ(«(е1ау) 0 1 0 О О 0 1 0 О ъа1СВ(а) и++ 61дпа1В (оЕ1а«'у): 13 -~~иа1В (а, 14 0 0 0 0 1 0 и ра1 ~ецап (рго««~««пег, сопзО~аег) ' 0 1 1 1 1 1 1 1 1 0 1 1 0 0 1 1 0 1 1 О О 0 0 О 0 -1 О -1 О 275 Часть 2.
средством ц елой переменной и = 1и — оыс. Для осуществления в -лючения используется семафор з; семафор с(е1ау применяется для о требителя при пустом буфере. стинг 5,8. [Неверное1 решение задачи производитель/потребитель с использованием бинарных семафоров Решение представляется достаточно простым и очевидным. ро ным. П из ожет добавлять данные в буфер в любой момент времени. Перед доб, н выполняет иа1~Б(з), а после добавления — з1диа1Б(з,, з ) чтобы ать обращение к буферу других производителей или потребителя на перации добавления данных в буфер. Кроме того, при работе в кр азделе производитель увеличивает значение и. Если и =- 1, то п р д =- 1 то пе ед этиз~ ением данных в буфер он был пуст, так что производитель вь| 1та1В (с)е1ау), чтобы сообщить об этом потребителю.
Потребитель на жидания производства первого элемента, используя вызо в ов жа1СБ(с)е1 ем потребитель получает данные из буфера и уменьшает значение и .ритическом разделе. Если производители опережают потребителя (д аспространенная ситуация), то потребитель будет редко блокирован с , поскольку и обычно положительно. Следовательно, благополучно работаю д и производитель, и потребитель.
Тем не менее в предложенной программе имеется один изъян. Когда потрель исчерпывает буфер, он должен сбросить семафор ае1ау с помощью инсткцпи .' (и == О) на1ГБ(бе1ау);, чтобы дождаться размещения данных в б фере производителем. Рассмотрим сценарий, приведенный в табл. 5.2. В стро- 1.1 потребитель не выполняет операцию ыа1~В. Он действительно исчерпал б фар и установил г. равным 0 в строке 8, но до проверки значения и в строке 14 было изменено производителем. В результате з' (;на1Б не соответствует редшестзующему иа1ГВ. Значение и, равное -1 в строке 20, означает, что поебитель пытается извлечь из буфера несуществующий элемент.
Простое пере- и щение проверки в критический раздел потребителя недопустимо, так как может привести к взаимоблокировке (например, после строки 8). Решение проблемы заключается во введении вспомогательной переменной, значение которой присваивается в критическом разделе и используется вне его, как показано в листинге 5.9. Внимательно рассмотрев приведенный код, вы убедитесь в отсутствии возможных взаимоблокировок. Таблица 5.2 Возможный сценарий работы программы из листинга 5.8 (и==О) ыа1~В (Де1ау) атоаа1В(а) ( и.=-=о ) ыа 1 1 В ( Де 1 а у ) а1Яиа1В (а) ' ПаРаллельные вычисления: взаимоисключения... ,ер,,е~Лс»ге и =- О; ~елерпаге Б = 1; »а„',', ргааисег() с и» изги зеи1ярЬаге я = 1, лагу эдзар)'аге с(е1зу = О; рга-(исег() ргас(исе(); хе1'(в); эрреиа()' зтаие1(з); В1апа1(и)р ргабисе(); »»»»3.'».
а ( э )» ерреиа(); и+1; (и == 1) эхдие1В(ае1еу); зт~ие1В (э); '»»ата салзитег() ( хЬ)1е(алие) ~»вас (Г~); ыа1г (э) р ~еМе (); е аие1(Б); сапяитйе(); »'* .()скальная пере~~еинзя / ие1аа (ае1ау); ыЬ11е ( гие) чауб Гсл1и () ( рэгЬед1п (ргааисег» саиеитег); и = О; регЬеа1и (ргабисег» сапе.цпег); Блокировка: Ронзво и дягель: вставка в полный буфер ль" удаление из пустого буфера Деблокирование: Потребитель: удаление элемента из буфера Производитель: вставка элемента в буфер Часть 2. 1стинг 5.9. Верное решение задачи производитель/потребитель с исполъзованием бинарных семафоров ыа1",В(э); саМ()» и »' П = Й» з1аие15(Я)' саиеигж (): 1й (п~ ==- О) иаусБ (с(е1ау); Несколько более простое решение (приведенное в листинге 5.