Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
03-21-12 Параллельные вычисления.DOC
Скачиваний:
5
Добавлен:
23.08.2019
Размер:
322.56 Кб
Скачать

7.3.2. Инструкция обмена

Выполнение команды Swap (обменять значения), обменивающей два значения, находящихся в памяти, можно проиллюстрировать следующей функцией:

Void Swap(int register, int memory);

{

int temp;

temp = memory;

memory = register;

register = temp;

}

Инструкция обменивает содержимое регистра и ячейки памяти. В процессе ее выполнения доступ к ячейке памяти для всех остальных процессов блокируется.

В листинге 7.4 показан протокол взаимных исключений, основанный на использовании описанной инструкции. Разделяемая переменная bolt инициализируется нулевым значением. У каждого процесса имеется локальная переменная key, инициализированная значением 1. В критический раздел может войти только один процесс, который обнаруживает, что значение переменной bolt равно 0. Этот процесс запрещает вход в критический раздел всем другим процессам путем установки значения bolt, равным 1. Выйдя из критического раздела процесс переустанавливает значение bolt, равным 0, тем самым позволяя другому процессу войти в критический раздел.

Листинг 7.4. Аппаратная проверка взаимных исключений. Инструкция обмена

const int n = /* Количество процессов */;

int bolt;

void P(int I)

{

int keyi;

while(true)

{

keyi = 1;

while(keyi != 0)

Swap(keyi, bolt);

/* Критический раздел */

Swap(keyi, bolt);

/* остальная часть кода */

}

}

void main()

{

bolt = 0;

parbegin(P(1),P(2),…,P(n));

}

Если bolt = 0, то в критическом разделе нет ни одного процесса. Если bolt = 1, то в критическом разделе находится ровно один процесс, а именно тот, переменная key которого имеет нулевое значение.

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

Bolt + ∑I keyi = n

Примером приведенных инструкций может служить тот факт, что многие компьютеры, особенно разработанные с расчетом на несколько процессоров, имеют команду TSL RX,LOCK (Test and Set Lock – проверить и заблокировать), которая действует следующим образом. В регистр RX считывается содержимое слова памяти LOCK, а в ячейке памяти LOCK сохраняется некоторое ненулевое значение. Гарантируется, что операция считывания слова и сохранения неделима. Процессор, выполняющий команду TSL, блокирует шину памяти, чтобы остальные процессоры не могли обратиться к памяти.

Воспользуемся командой TSL. Пусть совместно используемая переменная Lock управляет доступом к разделяемой памяти. Если значение переменной Lock равно 0, любой процесс может изменить его на 1 и обратиться к разделяемой памяти, и затем изменить его обратно на 0, пользуясь обычной командой move.

Как использовать эту команду для выполнения взаимоисключения? Решение приведено в листинге 7.5, написанное на фиктивном ассемблере.

Листинг 7.5. Вход-выход из критической области с помощью команды TSL

Enter_Region:

TSL Register,Lock ; значение Lock копируется в регистр, значение ; Lock устанавливается равным 1

CMP Registr,#0 ; старое значение Lock сравнивается с 0

JNE Enter_Region ; если Lock<>0, блокировка уже была

; установлена, поэтому цикл завершается

RET ; возврат к вызывающей программе, процесс

; вошел в критическую область

Leave_Region:

MOVE Lock,#0 ; занесение 0 в переменную Lock

RET