Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Автомат.doc
Скачиваний:
1
Добавлен:
24.09.2019
Размер:
187.39 Кб
Скачать

Задание 1.

Процесс 1

Процесс 2

process P1 ;

begin ...

While true do

begin …

request ( R1, 1) ;

...

request ( R2, 1) ;

...

release ( R2, 1) ;

...

release ( R1, 1) ;

...

end

...

end.

process P2 ;

begin ...

While true do

begin …

request ( R2, 1) ;

...

request ( R1, 1) ;

...

release ( R2, 1) ;

...

release ( R1, 1) ;

...

end

...

end.

Мы построили граф состояний системы. В данном случае тупик возможен. Тупиковая ситуация выделена.

Задание 2

Задание 3. Решить программным способом задачу взаимного исключения. Являются ли приведенные ниже процедуры решением поставленной задачи? Если нет, объясните, когда могут возникнуть ошибки?

Решение:

process INIT; common boolean C1. C2;

begin С1:=false; С2:=false; start(P1); start(P2); end;

process P1;

Begin

while true do

begin BEFORE1; C1:=true; while C2 do ; CS1; C1:=false; AFTER1; end

end;

process P2;

Begin

while true do

begin BEFORE2; while C1 do ; C2:=true; CS1; C2:=false; AFTER2; end

end;

Данное решение не гарантирует, что оба процесса не могут одновременно оказаться в критической секции. Приведем контрпример:

В начальный момент C1=false. Процесс P2 пройдет цикл while C1 do ; После этого запустится процесс P1 и выполнится присваивание C1:=true; и цикл while C2 do ; и первый процесс беспрепятственно прошел в критическую секцию. После этого продолжается процесс P2. Цикл он уже прошел, поэтому присваивает C2:=true и сам тоже попадает в критическую секцию.

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

Задание 4. Решить задачу взаимного исключения, используя логические переменные и процедуру перевода процесса в состояние задержки (приостановки) Delay(T), где параметр T задает время задержки процесса (время, на которое он выводится из конкуренции за время процессора).

Решение:

process INIT; common boolean C1. C2;

begin С1:=false; С2:=false; start(P1); start(P2); common real T1, T2; end;

process P1;

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

Begin

while true do

begin BEFORE1;

C1:=true;

while C2 do

begin

C1:=false;

T1:=random;

delay(T1);

C1:=true;

end;

CS1; C1:=false;

AFTER1;

end

end;

process P2;

Begin

while true do

begin BEFORE2;

C2:=true;

while C1 do

begin

C2:=false;

T2:=random;

delay(T2);

C2:=true;

end;

CS1; C2:=false;

AFTER2;

end

end;

Задание 5. Алгоритм Деккера можно сформулировать следующим образом:

Чтобы организовать работу N процессов нужно завести очередь, в которой будут храниться все процессы желающие получить доступ к КС. Для облегчение работы с очередью создадим несколько процедур: add (N,key) ( добавляет в конец очереди элемент со значением N и индивидуальным ключом key), del (key) (проверяет, совпадает ли ключ головного элемента очереди с key и удаляет, если совпал) и две функции: check(N) (сравнивает номер процесса в голове списка с N. Выдает true если они различны) и numhead ( возвращает номер первого элемента очереди). Уникальный ключ нужен, чтобы процесс мог удалить из очереди только себя, я не какой-либо другой процесс. Каждый процесс добавляет в очередь только себя. Вместо C1, … ,CN заведем массив mas булевского типа.

Процедура инициализации

Первый процесс

N-ый процесс

procedure INIT;

common mas;

common integer N ;

integer i;

begin

for i:=1 to 2000 do

mas[i]:=false;

Key:=random+1;

add (1,key)

start(P1,key) ;

Key:=random+1;

start(Pn,key)

end INIT .

process P1(key:int64);

common mas ;

begin

while true do

begin BEFORE1 ;

add(1,key);

mas[1] := true ;

while check(1) do

begin

if numhead<>1 then

begin

mas[1] := false ;

while numhead <>1 do ;

mas[1] := true ;

end

end ;

CS1 ;

del (key);

mas[1] := false;

AFTER1 ;

end

end P1 .

process Pn(key:int64);

common mas;

begin

while true do

begin BEFOREn ;

add(N,key);

mas[N] := true ;

while check(N) do

begin

if numhead<>N then

begin

mas[N] := false ;

while numhead <>N do ;

mas[N] := true ;

end

end ;

CSn ;

del (key);

mas[N] := false;

AFTERn ;

end

end Pn .

Задание 6. Решается ли в приведенных ниже программах проблема взаимного исключения (random – процедура, генерирующая случайное число, delay(T) – процедура задержки процесса на время T, в течение которого процесс не будет конкурировать за время процессора)?

process INIT; common boolean C1, C2; common integer N; common real T1, T2;

begin С1:=false; С2:=false; T1:= random; T2:= random; N:=1; start(P1); start(P2); end;

process P1;

Begin

while true do

begin BEFORE1;

C1:=true;

while C2 and (N<>1) do delay(T1);

CS1;

C1:=false; N:=2;

AFTER1;

end

end;

process P2;

Begin

while true do

begin BEFORE2;

C2:=true;

while C1 and (N<>2) do delay(T2);

CS2;

C2:=false; N:=1;

AFTER2;

end

end;

Допустим, второй процесс попробует зайти в критическую секцию. С1 еще false, поэтому он пройдет While и встанет перед критической секцией. В это время пойдет первый процесс. Т.к. N=1, то он тоже пройдет через while. После этого оба процесса могут попасть в критическую секцию.

Задание 7 : написать процедуры, моделирующие семафорные примитивы для общего семафора (допускаются только неотрицательные значения целочисленной переменной, моделирующей считающий семафор). При написании процедур можно использовать бинарные семафоры. Ниже приведен код процедур PP и VP, которые моделируют работу семафорных примитивов для общего семафора в соответствии с поставленной задачей. Решена ли задача? Найти в приведенном ниже псевдокоде ошибки, объяснить и исправить их (привести примеры, иллюстрирующие возможные проблемы), если они есть.

1 Решение:

Init: proc (var S: integer; value: integer);

common binary semaphore B1, B2;

begin B1:=1; B2:=1; S:=value end;

PP: procedure (var S: integer); common binary semaphore B1, B2;

Begin P(B2); P(B1); S:=S–1; if S>0 then V(B2); V(B1) end;

VP: procedure (var S: integer); common binary semaphore B1, B2;

Begin P(B1); S:=S+1; V(B1); V(B2 ) end;

Задача не решена, т.к. значение S может стать отрицательным. Пример: пусть у нас есть две единицы ресурса и N процессов, где N>2. Тогда каждый процесс может сделать один вызов PP, после этого вызвать VP и остановиться в VP перед V(B2);. Дальше, процессы по очереди вызовут PP и спокойно пройдут через P(B2), завершая каждый VP, остановятся перед P(B1); Дальше, каждый процесс может завершить PP, уменьшив S на единицу, т.е. S станет отрицательным, т.к. N>2 , что противоречит условию.

2

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

Решение:

Init: proc (var S: integer; value: integer);

common binary semaphore B1, B2;

begin B1:=1; B2:=1; S:=value end;

PP: procedure (var S: integer);

common binary semaphore B1, B2;

Begin P(B2); P(B1); S:=S–1; V(B1) end;

VP: procedure (var S: integer);

common binary semaphore B1, B2;

Begin P(B1); S:=S+1; V(B1); V(B2 ) end;

3 Решение:

I

Пусть ресурсов K, а процессов N>K. Каждый процесс зайдет сначала в PP, потом в VP и встанет перед V(B2). Затем, каждый процесс вызовет PP, пройдет P(B2), завершая VP, пройдет условие while S<=0 do; и остановится перед P(B1). После того, как все процессы соберутся перед P(B1) они могут завершить PP, сделав S отрицательным, т.к. N>K.

nit: proc (var S: integer; value: integer);

common binary semaphore B1, B2;

begin B1:=1; B2:=1; S:=value end;

PP: procedure (var S: integer);

common binary semaphore B1, B2;

Begin P(B2); while S<=0 do; P(B1); S:=S–1; V(B1); V(B2) end;

VP: procedure (var S: integer);

common binary semaphore B1, B2;

Begin P(B1); S:=S+1; V(B1); V(B2 ) end;

4

Этот вариант вообще не соответствует принципам работы общего семафора, т.к. PP должен дождаться освобождения ресурса и сам его взять, а он вместо этого ничего не делает и завершает работу. Если процесс «думает», что после PP он может получить доступ к ресурсу (КС) и что он потом этот ресурс должен отдать, то вызовов PP и VP будет одинаковое кол-во,

Но тогда, например, при двух единицах ресурса вначале после трех вызовов PP а потом трех VP в итоге получим S=3, т.е. ресурсов якобы стало больше, но на самом-то деле не стало.

Решение:

Init: proc (var S: integer; value: integer);

common binary semaphore B;

begin B:=1; S:=value end;

PP: procedure (var S: integer);

common binary semaphore B;

Begin P(B); if S>0 then S:=S–1; V(B) end;

VP: procedure (var S: integer);

common binary semaphore B;

Begin P(B); S:=S+1; V(B) end;

Поставленную в начале задачу можно решить посредством третьего семафора:

Решение:

Init: proc (var S: integer; value: integer);

common binary semaphore B1, B2, B3;

begin B1:=1; B2:=1; B3:=1; S:=value end;

PP: procedure (var S: integer); common binary semaphore B1, B2;

Begin P(B3); P(B2); P(B1); S:=S–1; if S>0 then V(B2); V(B1); V(B3) end;

VP: procedure (var S: integer); common binary semaphore B1, B2;

Begin P(B1); S:=S+1; V(B1); V(B2 ) end;

Таким образом внутри P(B3); V(B3) сможет находиться только один процесс, что позволяет условию if S>0 then V(B2); эффективно работать, задерживая на P(B2); процессы, в случае нехватки ресурсов, до их освобождения.

Задание 8: написать процедуры, моделирующие семафорные примитивы для общего семафора (допускаются любые значения целочисленной переменной, моделирующей считающий семафор). При написании процедур можно использовать бинарные семафоры. Ниже приведен код процедур PP и VP, которые моделируют работу семафорных примитивов для общего семафора в соответствии с поставленной задачей. Решена ли задача? Найти в приведенном ниже псевдокоде ошибки, объяснить и исправить их (привести примеры, иллюстрирующие возможные проблемы), если они есть.