Глава_1 (1085730), страница 9

Файл №1085730 Глава_1 (Методическое пособие по Операционным системам) 9 страницаГлава_1 (1085730) страница 92018-01-12СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 9)


Рис. 2.18. Время обеда на факультете философии

В листинге 2.10 представлено очевидное решение проблемы. Процедура take_ fork ждет, пока указанная вилка не освободится, и берет ее. К сожалению, это ре­шение неверно — представьте себе, что все пять философов возьмут одновремен­но свои левые вилки. Каждый останется без правой вилки, и произойдет взаимо­блокировка.

Листинг 2.10. Неверное решение проблемы обедающих философов

#define N 5 /* Количество философов */

void philosospher (int i) /* 1 - номер философа, от 0 до 4 */

{

while(TRUE) {

think (); /* Философ размышляет */

take_fork (i); /* Берет левую вилку */

take fork ((i+1) % N); /* Берет правую вилку */

eat () ; /* Спагетти, ням-ням */

put_fork(i); /* Кладет на стол левую илку

put_fork((I + 1)%N);

}}

Можно изменить программу так, чтобы после получения левой вилки прове­рялась доступность правой. Если правая вилка недоступна, философ отдает левую обратно, ждет некоторое время и повторяет весь процесс. Этот подход также не будет работать, хотя и по другой причине. Если не повезет, все пять философов могут начать процесс одновременно, взять левую вилку, обнаружить отсутствие правой, положить левую обратно на стол, одновременно взять левую вилку, и так до бесконечности. Ситуация, в которой все программы продолжают работать сколь угодно долго, но не могут добиться хоть какого-то прогресса, называется зависа­нием процесса (по-английски starvation, буквально «умирание от голода». Этот термин применяется даже в том случае, когда проблема возникает не в итальян­ском или китайском ресторане, а на компьютерах).

Вы можете подумать: «Если философы будут размышлять в течение некоторого случайно выбранного промежутка времени после неудачной попытки взять правую вилку, вероятность того, что все процессы будут продолжать топтаться на месте хотя бы в течение часа, невелика». Это правильно, и для большинства приложений повторение попытки спустя некоторое время не является проблемой. Например, в локальной сети Ethernet в ситуации, когда два компьютера посылают пакеты одновременно, каждый должен подождать случайно заданное время и повторить попытку — на практике это решение хорошо работает. Тем не менее в некоторых приложениях предпочтительным является другое решение, работающее всегда и не зависящее от случайных чисел (например, в приложении для обеспечения безопасности на атомных электростанциях).

В листинг 2.10 можно внести улучшение, исключающее взаимоблокировку и зависание процесса: защитить пять операторов, следующих за запросом think, бинарным семафором. Тогда философ должен будет выполнить операцию down на переменной mutex прежде, чем потянуться к вилкам. А после возврата вилок на место ему следует выполнить операцию up на переменной mutex. С теоретической точки зрения решение вполне подходит. С точки зрения практики возникают про­блемы с эффективностью: в каждый момент времени может есть спагетти только один философ. Но вилок пять, поэтому необходимо разрешить есть в каждый мо­мент времени двум философам.

Решение, представленное в листинге 2.11, исключает взаимоблокировку и по­зволяет реализовать максимально возможный параллелизм для любого числа фи­лософов. Здесь используется массив state для отслеживания душевного состояния каждого философа: он либо ест, либо размышляет, либо голодает (пытаясь полу­чить вилки). Философ может начать есть, только если ни один из его соседей не ест. Соседи философа с номером i определяются макросами LEFT и RIGHT (то есть если i = 2, то LEFT - 1 и RIGHT= 3).

Листинг 2.11. Решение задачи обедающих философов

#define N 5 /* Количество философов */

#define LEFT (i+N,l)%N /* Номер левого соседа философа с номером i */

#define RIGHT (i+1)%N /* Номер правого соседа философа с номером 1 */

#define THINKING 0 /* Философ размышляет */

#define HUNGRY 1 /* Философ пытается получить вилки */

#define EATING 2 /* Философ ест */

typedef int semaphore; /* Семафоры - особый вид целочисленных переменных */

int state[N]; /* Массив для отслеживания состояния каждого философа */

semaphore mutex = 1; /* Взаимное исключение для критических областей */

semaphore s[N]; /* Каждому философу по семафору */

void philosopher (int i) /* i - номер философа, от 0 до N-1 */

{

while (TRUE) { /* Повторять до бесконечности */

think (); /* Философ размышляет */

take_forks (i); /* Получает две вилки или блокируется */

eat (); /* Спагетти, ням-ням */

put_forks (i); . /* Кладет на стол обе вилки */
} }

void take_forks(int i) /* i - номер философа, от 0 до N-1*/

{

down(&mutex); /* Вход в критическую область */

state[1] = HUNGRY; /* Фиксация наличия голодного философа */

test(i): /* Попытка получить две вилки */

up(&mutex); /* Выход из критической области */

down(&s[i]); /* Блокировка, если вилок не досталось */

void put_forks(i) /* i - номер философа, от 0 до N-1*/

{

down(&mutex); /* Вход в критическую область */

state[i] = THINKING; /* Философ перестал есть */

test(LEFT); /* Проверить, может ли есть сосед слева */

test(RIGHT): /* Проверить, может ли есть сосед справа */

up(&mutex): /* Выход из критической области */

}

void test(i) /* i - номер философа, от 0 до N-1*/

{

if (state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING) { state [i] = EATING;

up(&s[i]); } }

В программе используется массив семафоров, по одному на философа, чтобы блокировать голодных философов, если их вилки заняты. Обратите внимание, что каждый процесс запускает процедуру philosopher в качестве своей основной про­граммы, но остальные процедуры take_forks, put_forks и test являются обычными процедурами, а не отдельными процессами.

Проблема читателей и писателей

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

Листинг 2.12. Решение проблемы читателей и писателей

typedef int semaphore; /* Воспользуйтесь своим воображением */

semaphore mutex = 1; /* Контроль доступа к rс */

semaphore db = 1: /* Контроль доступа к базе данных */

int rс = 0; /* Количество процессов, читающих или желающих читать */

void reader(void) {

while (TRUE) { Повторять до бесконечности */

down(&mutex) ; /* Получение монопольного доступа к гс */

гс = rc+1; /* Одним читающим процессом больше */

if (гс ==1) down(&db); /* Если этот читающий процесс - первый... */

up(&mutex); /* Отказ от монопольного доступа к гс */

read_data_base(); /* Доступ к данным */

down( &mutex ); /* Получение монопольного доступа к гс */

rc = rc-1 ; /* Одним читающим процессом меньше */

if (rc == 0) up(&db); /* Если этот читающий процесс - последний..

up (&mutex); /* Отказ от монопольного доступа к гс */

use_data_read (); /* Вне критической области */

} }

void writer (void)

{

while (TRUE) {

think_up_data (); /* Вне критической области */

down(&db); /* Получение монопольного доступа */

write_data_base();/* Запись данных */

up(&db); /* Отказ от монопольного доступа */

} }

Первый читающий процесс выполняет операцию down на семафоре db, чтобы получить доступ к базе. Последующие читатели просто увеличивают значение счетчика rс. По мере ухода читателей из базы значение счетчика уменьшается, и последний читающий процесс выполняет на семафоре db операцию up, позволяя блокированному пишущему процессу получить доступ к базе.

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

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

Чтобы избежать такой ситуации, нужно немного изменить программу: если пишущий процесс ждет доступа к базе, новый читающий процесс доступа не по­лучает, а становится в очередь за пишущим процессом. Теперь пишущему процес­су нужно подождать, пока базу покинут уже находящиеся в ней читающие про­цессы, но не нужно пропускать вперед читающие процессы, пришедшие к базе после него. Недостаток этого решения заключается в снижении производительно­сти, вызванном уменьшением конкуренции. В [78] представлено решение, в кото­ром пишущим процессам предоставляется более высокий приоритет.

Проблема спящего брадобрея

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

В предлагаемом решении используются три семафора: customers, для подсчета ожидающих посетителей (клиент, сидящий в кресле брадобрея, не учитывается — он уже не ждет); barbers, количество брадобреев (0 или 1), простаивающих в ожи­дании клиента, и mutex для реализации взаимного исключения. Также использу­ется переменная waiting, предназначенная для подсчета ожидающих посетителей.

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

Решение представлено в листинге 2.13. Когда брадобрей приходит утром на работу, он выполняет процедуру barber, блокируясь на семафоре customers, посколь­ку значение семафора равно 0. Затем брадобрей засыпает и спит, пока не придет первый клиент.

Листинг 2.13. Решение проблемы спящего брадобрея

#define CHAIRS 5 /* Количество стульев для посетителей */

typedef int semaphore; /* Догадайтесь сами */

semaphore customers = 0; /* Количество ожидающих посетителей */

semaphore barbers = 0; /* Количество брадобреев, ждущих клиентов */

semaphore mutex = 1; /* Для взаимного исключения */

int waiting = 0; /* Ожидающие (не обслуживаемые) посетители */

void barber(void) {

while (TRUE) {

down(&customers); /* Если посетителей нет, уйти в состояние ожидания */

down(&mutex); /* Запрос доступа к waiting */

waiting = waiting - 1; /* Уменьшение числа ожидающих посетителей */

up(&barbers); /* Один брадобрей готов к работе */

up(&mutex) ; /* Отказ от доступа к waiting */

cut_hair (); /* Клиента обслуживают (вне критической области)*/

Характеристики

Тип файла
Документ
Размер
2,72 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6458
Авторов
на СтудИзбе
304
Средний доход
с одного платного файла
Обучение Подробнее