- •Лекция 6: Реализация взаимного исключения
- •Способы реализации взаимного исключения
- •На основе инструкций чтения-записи памяти
- •На основе запрета / разрешения прерываний (однопроцессорные)
- •На основе инструкции «Test & Set»
- •Семафоры
- •Class Semaphore {
- •Реализация семафоров для многопроцессорных машин p: V:
- •Счетчик событий
Class Semaphore {
int count;
ThreadDescriptor* queue;
Pubic:
Semaphore(int n) { count = n; queue = null; }
Void P();
Void V();
};
void Semaphore::P() { void Semaphore::V() {
If(count>0) count--; if(queue не пуста) {
else { //Один в очередь готовых
//Поставить в очередь queue }
// Позвать планировщик else
} count++;
} }
Двоичный семафор:Начальное значение переменной семафора равно 1. ОперацияPставит процесс в очередь, если значение переменной семафора 0, сбрасывает переменную в 0, если она равнялась 1. ОперацияVосвобождает один процесс из очереди к семафору, если очередь не пуста. Если очередь пуста, то присваивает переменной семафора 1.
Применение семафора
Взаимное исключение
// Начальное значение счетчика семафора 1.
P();
Критическая секция;
V();
Ожидание некоторого события
P() – при нулевом начальном значении будет ждать, пока кто-то другой сообщит о наступлении события выполнив операциюV().
Задача о «производителе и потребителе»
Производитель передает данные потребителю через кольцевой буфер ограниченной емкости.
Условия синхронизации:
Производитель должен ждать, если буфер полон.
Потребитель должен ждать, если буфер пуст.
Операции с буфером – критическая секция, т.е. работать с буфером может только один процесс.
Правило большого пальца:число семафоров, необходимое для решения задачи равно числу условий синхронизации.
int size = 10;
Semaphore mutex(1);
Semaphore fill(0);
Semaphore empty(size);
void Producer() { Void Consumer() {
// Подготовить data fill.P();
empty.P(); mutex.P();
mutex.P(); RemoveFromBuffer(&data);
AddToBuffer(data); mutex.V();
mutex.V(); empty.V();
fill.V(); // Обработать data
} }
Вопросы:
Важен ли порядок Pопераций?
Важен ли порядок Vопераций?
Нужны ли изменения для 2 производителей и 2 потребителей?
Реализация семафоров для многопроцессорных машин p: V:
// Запрет прерываний // Запрет прерываний
while(test&set(v)==1); while(test&set(v)==1);
if(count>0) { if(очередь пуста) {
count--; count++;
v = 0; } else {
// разрешить прерывания // взять одного из очереди
return; // и в очередь готовых
} }
// поставить в очередь v = 0;
v = 0; // разрешить прерывания
Вызвать планировщик
Счетчик событий
Аналогичен семафорам, реализуется на основе следующих примитивов:
Read(E) - получить значение счетчика
Advance(E) - Увеличить счетчик на 1
Wait(E,v) - ждать покаE < v