Синхронизация параллельных процессов на низком уровне

Блокировка памяти

Взаимоисключения могут быть реализованы аппаратно, если сделать операции над памятью неделимыми. То есть, если каждый из процессов пытается поместить какие-либо значения в одну и ту же ячейку, то спор разрешается аппаратурой: если одному процессу разрешается выполнить операцию засылки немедленно, то другому приходится ждать пока первый не закончит операцию - такое разрешение спора и называется блокировкой памяти( storage interlock).

Попытаемся решить проблему критического участка для двух процессов X и Y с помощью некоторой переменной ключ, которая будет принимать значение true, когда процесс находится в своем критическом участке, и значение false - в противном случае. Прежде, чем войти в критический участок, процесс X проверяет ключ_Y другого процесса, чтобы убедится, что можно войти безопасно. Затем он включает свой собственный ключ_X и пользуется критическим участком.

 

var ключ_X, ключ_Y: boolean;

procedure процесс_Х;

begin

while (true) do

begin

while (ключ_Y) do;{ожидание, пока процесс Y не выйдет из критического участки}

ключ_X:=true;

{Критический участок Х}

ключ_X:=false;{признак выхода процесса X из критического участка}

{Оставшаяся часть процесса Х}

end;

end;

procedure процесс_Y;

begin

while (true) do

begin

while (ключ_X) do;{ожидание пока процесс X не выйдет из критического участка}

ключ_Y:=true;

{Критический участок Y}

ключ_Y:=false;{признак выхода процесса Y из критического участка}

{Оставшаяся часть процесса Y}

end;

end;

begin

ключ_X:=false;

ключ_Y:=false;

Parbegin

процесс_Х;

процесс_Y

Parend

end.

 

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

 

Алгоритм Деккера (Dekker’s Algorithm)

программную реализацию механизма взаимоисключения предложил голландский математик Деккер.

 

var C1,C2,очередь:integer;

procedure процесс_Х;

begin

C1:=1;

while (C2=1) do

begin

if очередь=2 then

begin

C1:=0;

while (очередь=2) do;

C1:=1;

end;

end;

{Критический участок процесса Х}

C1:=0;

очередь:=2;

{Оставшаяся часть процесса Х}

end;

procedure процесс_Y;

begin

C2:=1;

while (C1=1) do

begin

if очередь=1 then

begin

C2:=0;

while (очередь=1) do;

C2:=1

end;

end;

{Критический участок процесса Y}

C2:=0;

очередь:=1;

{Оставшаяся часть процесса Y}

end;

Begin

C1:=0;

C2:=0;

очередь:=1;

Parbegin

процесс_X;

процесс_Y

Parend

end.

 

В этом решении С1=1, когда процесс_Х хочет войти в свой критический участок. С2=1, когда процесс_Y хочет войти в свой критический участок, а переменная очередь указывает, чья очередь попытаться войти, при условии, когда оба процесса хотят выполнить свои критические участки.

 

Аппаратная реализация взаимоисключения: команда “проверка и установка” (testandset)


Рассмотрим вариант аппаратного решения данной проблемы. Наличие аппаратной команды testandset, которая осуществляет чтение переменной; запись ее значения в область сохранения и установку конкретного значения этой переменной, причем выполняет эти действия до конца без прерывания, значительно упрощает решение проблемы критического участка посредством блокировки памяти.

Рассмотрим выполнение команды testandset с параметрами общий и локальный. Операция читает значение параметра общий и присваивает его переменной локальный, а затем устанавливает в переменной общий значение 1.

Переменная общий разделяется между процессами, которые подлежат синхронизации по отношению к некоторому критическому ресурсу. У каждого процесса есть своя собственная переменная локальный_Х и локальный_Y.

Рассмотрим решение проблемы взаимоисключения с помощью операции testandset.

 

var общий: integer;

procedure процесс_Х;

var локальный_Х: integer;

begin

while (true) do

begin

локальный_Х:=1;

while (локальный_Х =1) do

testandset(локальный_Х, общий);

{Критический участок процесса Х}

общий:=0;

{Оставшаяся часть процесса Х}

end;

end;

procedure процесс_Y;

var локальный_Y: integer;

begin

while (true) do

begin

локальный_Y:=1;

while (локальный_Y =1) do

testandset(локальный_Y, общий);

{Критический участок процесса Y}

общий:=0;

{Оставшаяся часть процесса Y}

end;

end;

begin

общий:=0;

Parbegin

процесс_Х;

процесс_Y

Parend;

end.








Дата добавления: 2017-01-29; просмотров: 746;


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

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

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

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