Семафоры, мьютексы. Решение задач Читатель-Писатель и Производитель-Потребитель с помощью семафоров.
Семафор — целочисл. неотр. переменная, на которой определены две атомарные операции (атомарность обеспечивается реализацией).
V(S) — S++; // Неблокирующая — независимо от состояния S увеличиваем на 1 и идем дальше.
P(S) — S--; // Блокирующая — если S=0, поток будет ожидать его увеличения.
Типы семафоров:
1. Двоичные семафоры. Используются для обеспечения эксклюзивного доступа к ресурсу (решение задачи вз. искл.). Если S=1, ресурс свободен, S=0 — занят. Начальное значение — 1.
Semaphore S=1;
while (true ) {
P(S); // Захват ресурса в эксклюзивное пользование.
CS();
V(S); // Освобождение.
NCS();
}
2. Счетные семафоры — используются для контроля количества доступных ресурсов. Значение семафора — текущее количество свободных единиц ресурсов. Начальное значение — общее кол-во единиц ресурсов.
Пусть даны пять принтеров.
Semaphore S1=5, S2=1;
while (true ) {
P(S1); // Резервирование единицы ресурсов.
P(S2); // Получение эксклюзивного доступа к структуре, описывающей принтер.
Выбор принтера ();
V(S2);
Печать();
P(S2);
Освобождение принтера();
V(S2);
V(S1);
}
3. Мьютексы — специальный тип двоичных семафоров. Объект синхронизации, который может находиться в одном из двух состояний: свободен и занят. Определены две операции:
lock() / unlock()
acquire() / release()
___
Mutex M=unlocked;
while (true ) {
acquire(M);
CS();
release(m);
NCS();
}
Дополнительные свойства Мьютекса:
- Запоминание владельца. Освободить мьютекс может только тот поток, который его захватил.
- Рекурсивность. Поток, захвативший мьютекс, может повторно его захватить произвольное число раз. Для освобождения нужно соответсвующее число раз вызвать release.