Нижегородский государственный университет им. Н.И.Лобачевского
Опубликован: 02.10.2012 | Доступ: свободный | Студентов: 1744 / 191 | Длительность: 17:47:00
Специальности: Программист
Лекция 3:

Операционные системы - аспекты параллелизма

< Лекция 2 || Лекция 3: 123456 || Лекция 4 >

3.4. Решения задачи взаимного исключения

3.4.1. Использование запрещения прерываний

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

while( true ){
  DisableInterrupts();
  CS();                 /* Critical Section */
  EnableInterrupts();
  NCS();               /* Non-Critical Section */
}

Несмотря на то, что в частном случае однопроцессорной машины данное решение является корректным, оно имеет несколько недостатков.

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

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

3.4.2. Использование разделяемых переменных

Основная идея данного метода – использование некоторого набора разделяемых данных для согласования доступа к критическому ресурсу. Сначала рассмотрим несколько неправильных решений.

Решение 1.

// Разделяемые данные
bool flag0 = false;
bool flag1 = false;
// Код потока 0
while( true ){
while( flag1 ) ;
flag0 = true;
CS0(); //Critical Section
flag0 = false;
NCS0();//NonCriticalSection
}
// Код потока 1
while( true ){
while( flag0 ) ;
flag1 = true;
CS1(); //Critical Section
flag1 = false;
NCS1();//NonCriticalSection
}

flag0false, если поток 0 выполняется вне критической секции, true – если поток 0 выполняет критическую секцию. flag1 имеет тот же смысл для потока 1. Идея решения заключается в ожидании выхода потока-партнера из критической секции. Для доказательства ошибочности решения необходимо привести контрпример, который в данном случае должен представлять такую диаграмму выполнения потоков, при реализации которой нарушается одно из условий задачи взаимного исключения. Контрпример для решения 1 приведен на рис. 3.3 (поток 0 обозначен А, поток 1 – В; числа означают номера строк кода внутри внешнего цикла while).

Контрпример для решения 1 задачи взаимного исключения

Рис. 3.3. Контрпример для решения 1 задачи взаимного исключения

В3 соответствует выполнению потоком 1 его критической секции. Если считать, что выполнение В3 было прервано до завершения КС, то в момент, когда поток 0 (Поток А) приступит к выполнению своей КС (А3) мы получаем ситуацию, в которой два потока одновременно выполняются в критической секции, что противоречит условию 1 задачи взаимного исключения. Таким образом, мы доказали неверность данного решения и можем перейти к следующему.

Решение 2.

// Разделяемые данные
bool flag0 = false;
bool flag1 = false;
// Код потока 0
while( true ){
flag0 = true;
while( flag1 ) ;
CS0();
flag0 = false;
NCS0();
}
// Код потока 1
while( true ){
flag1 = true;
while( flag0 ) ;
CS1();
flag1 = false;
NCS1();
}

flag0 – false, если поток 0 выполняется вне критической секции и не желает начать ее выполнение, true – если поток 0 либо выполняет критическую секцию, либо ожидает возможности в нее войти. flag1 имеет тот же смысл для потока 1. Идея решения: поток заявляет о своем желании войти в критическую секцию, после чего ждет момента, когда это будет возможно.

Контрпример для данного решения приведен на Рис. 3.1

Контрпример для решения 2 задачи взаимного исключения

Рис. 3.1. Контрпример для решения 2 задачи взаимного исключения

К моменту, когда поток 0 начал выполнение строки А2, значение обоих флагов установлено в true, поэтому потоки будут бесконечно выполнять циклы А2 и В2 соответственно. Таким образом, решение 2 неверно, поскольку не выполняется условие (6) задачи взаимного исключения (решение о вхождении потоков в их критические секции ... является конечным во времени).

Решение 3.

// Разделяемые данные
bool flag0 = true;
bool flag1 = false;
// Код потока 0
while( true ){
while( ! flag0 ) ;
CS0();
flag0 = false;
flag1 = true;
NCS0();
}
// Код потока 1
while( true ){
while( ! flag1 ) ;
CS1();
flag1 = false;
flag0 = true;
NCS1();
}

flag0 – false, если поток 1 разрешил потоку 0 выполнять критическую секцию. flag1 имеет симметричный смысл для потока 1. Идея решения: поток выполняет критическую секцию, после чего разрешает выполнить критическую секцию потоку- партнеру.

Для данного решения нельзя построить диаграмму выполнения потоков, приводящую к недопустимому результату, однако в нем подразумевается поочередное выполнение критических секций потоками (что обычно не выполняется). Поток 0 не сможет выполнить свою критическую секцию в очередной раз, если до этого не выполнил КС поток 1. Таким образом, если потоку 0 необходимо дважды выполнить критическую секцию, а выполнение потока 1 было приостановлено вне критической секции, поток 0 будет ожидать повторной возможности входа в КС неопределенно долго, что нарушает условие (4) задачи взаимного исключения (остановка какого-либо потока вне его критической секции не должна влиять на дальнейшую работу потоков по использованию критического ресурса).

3.4.3. Алгоритмы Деккера и Петерсона

Решение Деккера основано на решении 2, но использует дополнительную переменную, упорядочивающую вход в критическую секцию при одновременном поступлении запросов на вхождение. Алгоритм Петерсона использует тот же самый принцип. Мы приведем именно его, поскольку его запись несколько проще.

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

/* i – номер потока (0 или 1) */
int ready[2] = {0, 0}; /* Намерение войти в КС */
int turn = 0; /* Приоритетный поток */
/* Код потоков */
while( true ) {
ready[i] = 1;
turn = 1 - i;
while( ready[1-i] && turn == 1-i )
;
CSi();
ready[i] = 0;
NCSi();
}

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

Существует обобщение алгоритма Деккера для N потоков – алгоритм булочной.

< Лекция 2 || Лекция 3: 123456 || Лекция 4 >
Дмитрий Остапенко
Дмитрий Остапенко

поддерживаю выше заданые вопросы

 

Павел Каширин
Павел Каширин

Скачал архив и незнаю как ничать изучать материал. Видео не воспроизводится (скачено очень много кодеков, различных плееров -- никакого эффекта. Максимум видно часть изображения без звука). При старте ReplayMeeting и Start в браузерах google chrome, ie возникает script error с невнятным описанием. В firefox ситуация еще интереснее. Выводится: 

Meet Now: Кукаева Светлана Александровна. 

Meeting Start Time: 09.10.2012, 16:58:04
Meeting Stop Time: 09.10.2012, 18:45:18
Recording Duration:01:47:14

Downloading...

Your Web browser is not configured to play Windows Media audio/video files.

Make sure the features are enabled and available.