Возможные проблемы при организации взаимного исключения при условии использования только блокировки памяти

Пусть имеется два или более циклических процессов с абстрактными критически­ми секциями, то есть каждый процесс состоит из двух частей: некоторой критиче­ской секции и оставшейся части кода, которая не работает с общими (критическими) переменными. Пусть эти два процесса асинхронно разделяют во времени единствен­ный процессор либо выполняются на отдельных процессорах, то есть каждый из них имеет доступ к некоторой общей области памяти, с которой и работают крити­ческие секции. Проиллюстрируем эту ситуацию с помощью рис. 7.3.

Рис.7.3. Модель взаимодействующих процессов

Задача вроде бы легко решается, если потребовать, чтобы процессы ПР1 и ПР2 вхо­дили в свои критические секции попеременно. Для этого одна общая переменная может хранить указатель на тот процесс, чья очередь войти в критическую секцию. Текст этого решения на языке, близком к Паскалю, приведен в листинге 7.1.

Листинг 7.1. Текст программы для первого решения

Var перекл : integer;

Begin перекл := 1; {при перекл=1 в критической секции находится процесс ПР1}

Parbegin


Средства синхронизации и связи взаимодействующих процессов_______________ 217

While true do Begin

while перекл = 2 do begin end; CS1: { критическая секция процесса ПР1 } перекл := 2:

PR1; { оставшаяся часть процесса ПР1 } End And

While true do Begin

while перекл = 1 do begin end: CS2: { критическая секция процесса ПР2 } перекл :- 1;

PR2: { оставшаяся часть процесса ПР2 } End Parend End.

Здесь и далее языковая конструкция следующего типа означает параллельность выполнения К описываемых последовательных процессов:

parbegin...Sll:S12; ... : S1N1 and... S21; S22; ... ; S2N2

and... SK1: SK2: ... : SKN1k parend

Конструкция из операторов S11; S12;...; S1N1 выполняется последовательно (опе­ратор за оператором), о чем свидетельствует наличие точки с запятой между ними.

Следующая языковая конструкция означает, что каждый процесс может выпол­няться неопределенно долгое время фактически бесконечное количество раз:

while true do begin S1; S2: SN end

Наконец, конструкция типа begin end означает просто «пустой» оператор. Итак, решение, представленное в листинге 7.1, обеспечивает нам взаимное ис­ключение в работе критических секций. Однако если бы фрагмент программы PR1 был намного длиннее, чем фрагмент PR2, или если бы процесс ПР1 был за­блокирован в секции PR1, или если бы процессор для ПР2 обладал более высо­ким быстродействием, то процесс ПР2 вскоре вынужден был бы ждать входа в свою критическую секцию CS2, хотя процесс ПР1 и был бы вне CS1. Такое ожи­дание могло бы оказаться слишком долгим, то есть для этого решения один про­цесс вне своей критической секции может помешать другому войти в свою кри­тическую секцию.

Попробуем устранить это блокирование с помощью двух общих переменных, ко­торые будут использоваться как флаги, указывая, находится или нет соответству­ющий процесс в своей критической секции. То есть с каждым из процессов ПР1 и ПР2 будет связана переменная, которая принимает значение true, когда процесс находится в своей критической секции, и false — в противном случае. Прежде чем войти в свою критическую секцию, процесс проверит значение флага другого про­цесса. Если это значение равно true, процессу не разрешается входить в свою кри­тическую секцию. В противном случае процесс установит собственный флаг и вой-


218 Глава 7. Организация параллельных взаимодействующих вычислений

дет в критическую секцию. Этот алгоритм взаимного исключения представлен в листинге 7.2.

Листинг 7.2. Второй вариант реализации взаимного исключения

Var перекл1.перекл2.: boolean: begin перекл1:=false;

neperкп:=false; parbegin

while true do begin

while перекл2 do begin end;

перекл1:=true:

CS1 { критическая секция процесса ПР1 } перекп1:=false:

PR1 { процесс ПР1 после критической секции } end and

while true do begin

while перекл1 do begin end; перекл2:=true:

CS2 { Критическая секция процесса ПР2 } перекп2:=false:

PR2 { процесс ПР2 после критической секции } end

parend end.

Данный алгоритм, увы, не гарантирует полного выполнения условия нахождения только одного процесса внутри критической секции. Отсутствие гарантий связано с различными, в общем случае, скоростями развития процессов. Поэтому, напри­мер, между проверкой значения переменной перекл2 процессом ПР1 и последую­щей установкой им значения переменной перекл1 параллельно выполняющийся процесс ПР2 может установить перекл2 в значение true, так как переменная пе­рекл! еще не успела установиться в значение true. Отсюда следует, что оба процес­са могут войти в свои критические секции одновременно.

Следующий (третий) вариант решения этой задачи (листинг 7.3) усиливает вза­имное исключение, так как в процессе ПР1 проверка значения переменной перекл2 выполняется только после установки переменной перекл1 в значение true (анало­гично для ПР2).

Листинг 7.3. Третий вариант реализации взаимного исключения

var перекл1. перекл2 : boolean; begin перекл1:=false; nepeкп2:=false: parbegin

ПР1: while true do begin перекл1:=true;


Средства синхронизации и связи взаимодействующих процессов____________ 219

while перекл2 do

begin end:

CS1 { критическая секция процесса ПР1 } перекл1:-false:

PR1 { ПР1 после критической секции } end and

ПР2: while true do begin

перекл2:=true: while перекл1 do

begin end:

CS2 { критическая секция процесса ПР2 } перекл2:=false:

PR2 { ПР2 после критической секции } end

parend end.

Алгоритм, приведенный в листинге 7.3, также имеет свои недостатки. Действи­тельно, возможна ситуация, когда оба процесса одновременно установят свои флаги в значение true и войдут в бесконечный цикл. В этом случае будет нарушено требо­вание отсутствия бесконечного ожидания входа в свою критическую секцию. То есть, предположив, что скорости исполнения процессов произвольны, мы получи­ли такую последовательность событий, при которой процессы вообще перестанут нормально выполняться.

Все рассмотренные попытки решить задачу взаимного исключения при выполне­нии критических секций иллюстрируют нам некоторые тонкие моменты, лежа­щие в основе этой проблемы, и показывают, что не все так просто.

Последний рассматриваемый вариант решения задачи взаимного исключения, опирающийся только на блокировку памяти, — это известный алгоритм, предло­женный математиком Деккером.

Алгоритм Деккера

Алгоритм Деккера основан на использовании трех переменных (листинг 7.4): пе-рекл1, перекл2 и ОЧЕРЕДЬ. Пусть по-прежнему переменная перекл1 устанавливает­ся в true тогда, когда процесс ПР1 хочет войти в свою критическую секцию (для ПР2 аналогично), а значение переменной ОЧЕРЕДЬ указывает, чье сейчас право сде­лать попытку входа при условии, что оба процесса хотят выполнить свои крити­ческие секции.








Дата добавления: 2016-09-20; просмотров: 913;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.007 сек.