Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
VSOS_2014.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.9 Mб
Скачать

17Переменные блокировки

Теперь попробуем найти программное решение. Рассмотрим одну совместно используемую переменную блокировки, изначально равную 0. Если процесс хочет попасть в критический участок, он предварительно считывает значение переменной блокировки. Если переменная равна 0, то процесс изменяет ее на 1 и входит в критический участок. Если же переменная равна 1, то процесс ждет, пока ее значение сменится на 0.

18Операция проверки и установки

Многие компьютеры имеют аппаратные операции, которые позволяют проверять и устанавливать содержимое слова (операция Test and Set Lock). Логику работы этой операции можно описать следующим образом:

function Test_and_Set(var target:Boolean):Boolean;

begin

Test_and_Set := target;

target := true;

end;

Главная отличительная особенность этой команды  ее выполнение не может быть прервано. Если предпринимается попытка одновременного выполнения двух таких команды (на разных процессорах), то они будут выполнены последовательно, в порядке, определяемом аппаратурой. Такой прием называется блокировкой памяти.

Если наша компьютерная система поддерживает такую команду, то мы можем организовать взаимное исключение, объявив переменную lock с начальным значением false. Пусть у нас имеется n процессов. Тогда структура процесса может быть следующей:

repeat

. . .

while Test_and_Set(lock) do

no-op;

критический участок

lock := false;

. . .

until false;

Этот алгоритм, однако, не удовлетворяет условию ограниченного ожидания.

Рассмотрим теперь алгоритм для синхронизации n процессов , удовлетворяющий этому требованию. Процессы должны использовать следующие структуры данных:

var waiting: array[0..n-1] of Boolean;

lock: Boolean;

Все они проинициализированы значением false.

Тогда структура процесса будет следующей:

var j: 0..n-1;

key: Boolean;

. . .

repeat

waiting[i] := true;

key := true;

while waiting[i] and key do

key := Test_and_Set(lock);

waiting[i] := false;

критический участок

j := (j + 1) mod n;

while (j <> i) and not waiting[j] do

j := (j + 1) mod n;

if i = j then

lock := false;

else

waiting[i] := false;

. . .

until false;

Процесс может войти в критический участок, если значение waiting[i] или key ложно. Переменная key получит значение false только если операция Test_and_Set выполнена. Процесс, первым выполнивший эту операцию, найдет это значение, равным false и войдет в критический участок, остальные процессы должны ждать. Переменная waiting[i] получит значение false только, когда другой процесс выйдет из критического участка, и только это обеспечивает требование взаимного исключения. Ограниченное ожидание обеспечивается за счет циклического просмотра, а освобождение критического участка – установкой значения переменной lock в false.

    1. Семафоры

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

Семафор – это переменная целого типа, которая, кроме начальной инициализации допускает только две простых операции: wait и signal.

Классическое определение этих операций:

wait(s): while s <= 0 do no-op;

s := S – 1;

Signal(s): s := S + 1;

Модификации значения семафора этими операциями выполняются неделимо. Пока один процесс модифицирует семафор, ни один другой процесс не имеет доступа к этому семафору. Кроме того, в случае wait(s) проверка значения семафора и его модификация также должны выполняться неделимо.

Такие семафоры называют счетными или считающими.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]