- •5. Взаимодействие и синхронизация процессов
- •5.1. Взаимодействие процессов (Лекция 9)
- •5.1.1. Способы взаимодействия процессов
- •5.1.1.1. Проблема синхронизации
- •5.1.1.2. Критические секции, средства коммуникации процессов
- •5.1.1.3. Способы взаимодействия процессов, понятия взаимного исключения, взаимной блокировки, голодания процессов
- •5.1.2. Взаимные исключения
- •5.1.2.1. Требования к взаимным исключениям
- •5.1.2.2. Алгоритмы Деккера и Петерсона реализации взаимного исключения
- •5.2. Семафоры и другие средства синхронизации (Лекция 10)
- •5.2.1. Синхронизация задач с помощью семафоров
- •5.2.1.1. Семафоры Дейкстры
- •5.2.1.2. Условная синхронизация с помощью семафоров
- •5.2.1.3. Планирование очереди процессов, ожидающих у семафора
- •5.2.2. Другие средства синхронизации: счётчики событий, секвенсоры, мониторы, передача сообщений
- •5.2.2.1. Счетчики событий и секвенсоры
- •5.2.2.2. Объекты синхронизации, регламентированные posix
- •5.2.2.3. Мониторы Хоара
- •5.2.2.4. Передача сообщений
- •5.3. Классические проблемы межпроцессного взаимодействия (Лекция 11)
- •5.3.1. Проблема "обедающих философов"
- •5.3.1.1. Описание проблемы "обедающих философов"
- •5.3.1.2. Решение (алгоритм) проблемы "обедающих философов"
- •5.3.2. Проблема "спящего брадобрея" (задача о парикмахерской)
- •5.3.2.1. Описание задачи о парикмахерской
- •5.3.2.2. Решение (алгоритм) задачи о парикмахерской
- •5.3.3. Задача "читателей и писателей"
- •5.3.3.1. Описание задачи читателей и писателей
- •5.3.3.2. Решение (алгоритм) задачи читателей и писателей
- •5.4. Взаимоблокировки (Лекция 12)
- •5.4.1. Возникновение взаимоблокировок
- •5.4.1.1. Проблема взаимоблокировок
- •5.4.2. Устранение взаимоблокировок
- •5.4.2.1. Запрещение запуска процесса
- •5.4.2.2. Запрет выделения ресурса
- •5.4.3. Обнаружение взаимоблокировок
- •5.4.3.1. Алгоритм обнаружения взаимоблокировок
- •5.4.3.2. Действия, выполняемые после обнаружения взаимоблокировки
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 в зависимости от идентификаторов процессов.
