Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции / 5_взаимодействие и синхронизация процессов.doc
Скачиваний:
103
Добавлен:
20.06.2014
Размер:
1.47 Mб
Скачать

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

Способы взаимодействия процессов можно классифицировать по степени осведомленности одного процесса о состоянии другого. В случае, когда процессы не осведомлены друг о друге, между ними имеет место конкуренция. Результат работы каждого процесса не зависит при этом от результатов работы других процессов, но возможно влияние одного процесса на время работы другого. Потенциальная проблема, возникающая в случае конкуренции процессов – необходимость взаимных исключений (mutualexclusion), если два или большее число процессов требуют доступ к одному неразделяемому ресурсу (см. п. 5.1.1.2). Осуществление взаимных исключений порождает две проблемы:

1) взаимную блокировку – ситуация, в которой несколько процессов занимают ресурсы, и каждый из них для продолжения работы должен получить доступ к занятому ресурсу из данного множества;

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

Если процессы косвенно осведомлены о наличии друг друга (разделяют доступ к некоторому объекту, например, буферу ввода/вывода), имеет место сотрудничество с использованием разделения. Результат работы одного процесса может зависеть от информации, полученной от других. Возможно влияние одного процесса на время работы других. При этом также возможны взаимное исключение, взаимоблокировка и голодание. Кроме того, существует проблема связи данных.

Когда процессы непосредственно осведомлены друг о друге между ними имеет место сотрудничество с использованием связи. Результат работы одного процесса может зависеть от информации, полученной от других. Также возможно влияние одного процесса на время работы других. Проблемы – взаимоблокировка и голодание.

5.1.2. Взаимные исключения

5.1.2.1. Требования к взаимным исключениям

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

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

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

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

Не делается никаких предположений о количестве процессов или их относительных скоростях работы.

Процесс остаётся в критическом разделе только в течение ограниченного количества времени.

Первый подход к выполнению перечисленных требований является программным и заключается в соблюдении всех требований самим процессом, без поддержки ОС (алгоритмы Деккера, Петерсона). Второй подход состоит в использовании машинных команд специального назначения.

5.1.2.2. Алгоритмы Деккера и Петерсона реализации взаимного исключения

Алгоритм Деккера (см. ниже) предполагает только элементарные взаимоисключения на уровне доступа к памяти, т.е. одновременный доступ (чтение и/или запись) упорядочивается при помощи некоторого механизма. Необходимо "навязать" определенный порядок действия двум процессам. Переменная turnуказывает, какой из двух процессов имеет право на вход в критическую секцию. Когда процессp0 намерен войти в критическую секцию, он устанавливаетflag[0] вtrueи проверяетflag[1]. Еслиflag[1] =false,p0 может немедленно войти в критическую секцию, иначеp0 проверяетturn. Еслиturn= 0, то сейчас – очередьp0 иp0 периодически проверяетflag[1].P1, в свою очередь, обнаружив, что сейчас не его очередь, в какой-то момент времени сбрасываетflag[1] вfalse. По окончанию работыp0 сбрасывает flag[0] вfalseи присваивает единицу переменнойturn.

Алгоритм:

Boolean flag[2];

Int turn;

Voidp0 ( )

{

While (true)

{

Flag[0] = true;

While (flag[1])

If (turn == 1)

{

Flag[0] = false;

While (turn == 1); //ничего не делать

Flag[0] = true;

}

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

turn= 1;

flag[0] =false;

//остальной код

}

}

voidp1 ()

{

//определение аналогично предыдущему, с заменой всех переменных на

//противоположные

}

void main ( )

{

flag[0] = false;

flag[1] = false;

turn = 1;

parbegin (p0, p1);

}

Алгоритм Петерсона реализации взаимного исключения изобретен в 1981 г. С этого момента алгоритм Деккера считается устаревшим.

#define FALSE 0

#define TRUE 1

#define N 2

intturn; /*чья сейчас очередь*/

int interested[N]; /*изначально все нули - FALSE*/

void enter_region (int process)

{

int other = 1-process; /*противоположный*/

interested[process]=TRUE; /*да, мы хотим войти*/

turn=process;

while(turn==process&&interested[other]==true); /*активное ожидание*/

}

void leave_region(int process)

{

interested[process]=FALSE; /*все, мы уходим*/

}

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

Активное ожидание – плохо. Кроме того, возникает проблема инверсии приоритета. Допустим, есть 2 процесса: HиL, причем приоритет Н>>L. Если Н оказался в ожидании, покаLне освободит некий ресурс, то Н в активном ожидании постоянно отнимает процессорное время у низкоприоритетного процессаL, не давая ему выйти из критической секции.