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

Строгое чередование

while(1)

{ while(turn);

goto_crit();

turn=1;

noncrit ();

}

while (1)

{ while(!turn);

goto_crit();

turn=0

noncrit ();

}

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

Активное ожидание - постоянная проверка значения переменной в ожидании некоторогго значения. Спин блокировка - блокировка, использующая активное ожидание.

Алгоритм Петерсона

#define n 2

int turn, interested [n];

void goto_crit (int proc)

{ int other;

other=1 - proc;

interested [proc]=TRUE;

turn=proc;

while (turn==proc&interested[proc]==TRUE);

}

void leave_crit

(int proc)

{

interested[proc]=FALSE;

}

команда TSL (test and set lock)

решение проблемы взаимного исключения с помощью команда тсл требует поддержки процессором такой команда. Принцип действия: в регистр считывается переменная блокировки а в эту переменную записывается некоторое ненулевое значение. Гарантируется, что операция чтения и сохранения недилимы. Если переменная лок управляет доступом к критическому ресурсу и значение переменной равно нулю, то любой процесс может обратиться к критическому ресурсу измениа значение лок на 1,а после выхода вкрнуть в нулевое значение команды mov.

Goto_crit ()

{: loop

tsl rx, lock

cmp rx, 0

je loop

}

leave_crit ()

{

mov lock, 0

}

недостаток: активное ожидание.

Примитивный межпроцессного взаимодействия

проблема инверсии приоритета:

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

Проблема производителя-потребителя примитив sleep wake. Существует программа производитель и программа потребитель, а также совместно используемый буфер ограниченного размера, который является критическим ресурсом. Ошибки возникают при попытке записи производителем в полный буфер либо считыванием потребителя из пустого буфера. Решение этой проблемы с помощью примитивов слип и вэйк.

#define n 10

int count=0

void producer (void)

{int item;

while (1)

{ item=produce ();

if (coutn==n) sleep ();

insert_item (item);

count++;

if (count==1) wake(consumer);

}

void consumer (void)

{ int item;

while (1)

{ if(!count) sleep();

item=remove_item();

count --;

if(count==n-1)

wake (produser);

consume_item (item);

}

}

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

Семофоры.

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

Операция довн сравниввает значение симофора с нулем. Если симофор больше нуля довн уменьшает значение симофора и возращает управление процессу. Если симофор равен нулю то процесс переводиться в состояние блокировки.

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

#define n 100

typedef int semaphore,

semaphore mutex=1,

semaphore empty=n,

semaphore full=0

void produccer (void)

{int item,

while (1) {item=produce(),

down(&empty);

down(&mutex);

insert(item);

up(&mutex);

up(&full);

}}

void consumer (void)

{int item;

while(1)

{down(&full);

down(&mutex);

item=remove();

up(&mutex);

up(&empu);

consume (item);

}}

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

Mutex - упрощенная версия симофора не способная считать а только управлять исключением одновременного доступа к критическим ресурсам. Простота реализации и эффективность делают мютексы полезными в случае реализации потоков в пространстве пользователя.

Mutex_lock:

tsl rx, mutex

cmp rx, 0

je ok

call thread_yield

jmp mutex_lock

ok: ret

-----------

mutex_unlock:

mov mutex, 0

ret

в отличие от активного ожидания реализация взаимного исключения с помощью мютексов предполагает добровольную блокировку потока и передачу управления к другому потоку.

Мониторы.

Реализация взамного исключения с помощью симофора предполагает детальную разработку с целбю не допустить взаимной блокировки. Для улучшения ситуации взаимоблокировки был предложен примитив синхронизации более высокого уровня, так называемый монитор. Монитор - набор структур переменыых и других структур данных обьединенных в особый модуль. Процессы могут вызывать процедуры монитора. Но у процидур объявленных вне монитора нет прямого доступа к его внутренним структурам. Реализации взаимных исключений способствуют такое свойство монитора что при обращении к монитору в любой момент времени активным может быть тока 1 процесс. Обычно первые несколько команд проверяют нет ли в мониторе активного процесса. Если есть то вызывающий процесс входит в состояние ожидания. Поскольку взаимные исключения обеспечивает компилятор а не программист вероятность ошибки гораздо меньше. Для блокировки процессов не способны продолжить свою деятельность были введены переменная состояния и операции вайд и сигнал.

Monitor prod_cohs

{ condition full, empty;

int count;

void insert (int item)

{ if (cout==n) wait (full);

insert_item(item);

count++;

if (count==1) signal (empty);

}

int remove (void)

{ if (!count)

wait (empty);

return (remove_item);

count--;

if (count==n-1)

signal (full);

}}

void produser (void)

{ while (1)

{ item=produce_item();

prod_cons.insert();

}

}

void consumer (void)

{ while (1)

{item=pred_cous.remove();

consume_item(item);}

}