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

19Использование семафоров

Рассмотрим использование семафоров для организации критических участков для n процессов . Эти процессы разделяют семафор mutex, инициализированный значением 1.

Схема работы процесса выглядит следующим образом:

repeat

. . . . .

wait(mutex);

критическая секция

signal(mutex);

. . . .

until false;

Можно применять семафоры и для решения других задач синхронизации. Например, рассмотрим два параллельно выполняемых процесса , в котором имеется оператор , и , в котором имеется оператор . Предположим, что оператор должен выполняться после оператора . Можно решить эту задачу путем использования общего семафора synch, инициализированного нулем.

Процесс будет содержать последовательность операторов:

S1;

signal(synch);

Процесс будет содержать последовательность операторов:

wait(synch);

S2;

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

20Реализация семафоров

Главным недостатком приведенного определения семафора является наличие цикла для организации ожидания. Пока один процесс выполняет свой критический участок, все остальные должны циклически выполнять вход в критический участок. Такое решение снижает эффективность работы. Во избежание этого, необходимо модифицировать описание семафора. Когда процесс выполняет операцию wait(s), а значение семафора меньше нуля, он должен перейти в состояние ожидания, то есть он должен себя заблокировать. Для этого процесс должен поместить себя в очередь, ассоциированную с данным семафором, изменить свое состояние и передать управление планировщику. Заблокированный процесс может быть возобновлен, когда несколько процессов выполнят операцию signal. При этом должна быть выполнена операция пробуждения (wakeup), перемещающая процесс в очередь готовых заданий.

Реализацию семафора можно определить следующим образом:

type semaphore = record

value: integer;

L: list of processes;

end;

Каждому семафору соответствует целое значение и список процессов.

wait(s): s.value := s.value – 1;

if s.value < 0 then

begin

add this process to s.L;

block;

end;

signal(s): s.value := s.value + 1;

if s.value <= 0 then

begin

remove a process P from s.L;

wakeup(P);

end;

Очередь ожидающих процессов может обслуживаться по методу FIFO или с помощью любой другой стратегии.

21Тупики и зависания

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

Для иллюстрации рассмотрим два процесса, P0 и P1, имеющих доступ к двум семафорам S и Q, первоначально установленным в 1.

P0

wait(S)

wait(Q)

.

.

.

signal(Q)

signal(S)

P1

wait(Q)

wait(S)

.

.

.

signal(S)

signal(Q)

Предположим, что процесс P0 выполнил wait(S), затем процесс P1 выполнил wait(Q). Когда процесс P0 выполнит wait(Q), он будет ожидать, пока процесс P1 выполнит операцию signal(S). Аналогично, процесс P1 будет ожидать, пока процесс P0 выполнит операцию signal(Q). Поскольку эти операции не могут быть выполнены, процессы P0 и P1 находятся в тупике.

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

Другой опасностью являются так называемые зависания (starvation), когда процесс находится в очереди к семафору неопределенно долгое время. Такая ситуация может, например, возникнуть, если очередь к семафору организована по методу LIFO.

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