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

5.2.1.2. Условная синхронизация с помощью семафоров

Пусть процесс А не может продолжаться, если процесс В не выполнил некоторое действие. Здесь нет критических секций, разделяемых переменных, но задача решается с использованием семафора, инициализированного нулем (рис. 4-5).

Семафор SА В

0; очередь пуста

0; А wait(S)

0; очередь пуста signal(s)

Рис. 4

Семафор SА В

0; очередь пуста

1; очередь пустаsignal(s)

0; очередь пуста wait(s)

Рис. 5

В первом случае (рис.4) процесс А достиг точки синхронизации раньше, чем процесс В сделал нужное действие. Во втором случае процесс А достиг точки синхронизации позже, чем процесс В сделал нужное действие. MSDN рекомендует данный способ для ожидания инициализации ресурсов.

Семафор, используемый в такой форме, называется приватным, так как ждать у него может лишь один процесс, зависимый от другого или других процессов.

5.2.1.3. Планирование очереди процессов, ожидающих у семафора

Планирование процессов, ожидающих у семафора, может осуществляться с использованием FIFO, однако существует две проблемы:

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

2) Низкоприоритетный процесс может стоять в очереди семафора перед процессов с более высоким приоритетом.

Вторая проблема в однопроцессорной системе решается просто – signal()освобождает все ожидающие в очереди у семафора процесса, после чего каждый из них снова выполняетwait(). После освобождения первым на выполнение будет направлен процесс с наиболее высоким приоритетом – он и получит семафор. Недостаток: системные затраты на многократное блокирование и разблокирование процессов.

Планирование по принципу FIFO подходит для систем:

– не требующих ответа в реальном времени;

– в которых процессы, ожидающие у семафора, обычно выполняются с одинаковыми приоритетами;

где очереди семафоров коротки.

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

5.2.2. Другие средства синхронизации: счётчики событий, секвенсоры, мониторы, передача сообщений

5.2.2.1. Счетчики событий и секвенсоры

Эти объекты предложены как альтернативы семафорам, но у них другой смысл. Они позволяют определить событие и подсчитать, сколько раз оно произошло, начиная с заданного момента времени.

Счётчики событий содержат внутри себя неотрицательный целый счётчик, изначально равный нулю. Доступны следующие функции такого объекта:

Advance() – увеличить счётчик на единицу;

Read() – считать текущее значение;

Await(int num) – приостановить выполнение текущего процесса, пока значение счётчика не достигнет значенияnum.

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

Секвенсоры упорядочивают параллельные процессы для выполнения действий в строго последовательном порядке. Секвенсор – тоже целое число, инициализированное нулём. Для него определена только одна операция ticket(), которая увеличивает значение на единицу и возвращает это значение. Секвенсор применяется совместно со счётчиком событий. Пример:

EventCount ec = new EventCount;

Sequencer sq = new Sequencer;

Int myturn;

myturn = sq.ticket(); //получить билет с очередным номером

ec.await(myturn);

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

ec.advance();

В данном примере порядок выполнения критических секций определяется порядком полученных ими номеров. "Хозяин" секвенсора может расставлять процессы в нужном ему порядке, если задаст нужный алгоритм функции ticket в зависимости от идентификаторов процессов.