Неполное решение задачи о парикмахерской

Основное тело программы активизирует процессы 50 клиентов, трех парик­махеров и одного кассира. Рассмотрим теперь назначение различных синхрони­зирующих операторов.

· Вместимость парикмахерской и дивана.Вместимость парикмахерской и дивана управляется семафорами max_capacity и sofa, соответственно. Каждый раз при попытке клиента войти в парикмахерскую значение сема­фора max_capacity уменьшается на 1; когда клиент покидает парикмахер­скую, оно увеличивается. Если парикмахерская заполнена, то процесс кли­ента приостанавливается функцией wait (max_capacity). Аналогично об­рабатывается и попытка присесть на диван.

· Емкость парикмахерских кресел. В наличии имеются три парикмахерских кресла, и следует обеспечить их корректное использование. Семафор barber_chair гарантирует одновременное обслуживание не более трех кли­ентов, так чтобы один клиент не оказался на коленях у другого. Клиент не поднимется с дивана до тех пор, пока не окажется свободным хотя бы одно кресло (вызов wait (barber_chair)), а каждый парикмахер сообщает о том, что его кресло освободилось (вызов signal (barber_chair)). Справед­ливый доступ к парикмахерским креслам гарантируется организацией оче­редей семафоров: клиент, который первым блокирован в очереди, первым же и приглашается на стрижку. Заметим, что если в процедуре клиента вы­зов wait (barber_chair) разместить после signal (sofa), то каждый кли­ент будет только присаживаться на диван, после чего немедленно вскаки­вать и занимать стартовую позицию у кресла, создавая излишнюю толкот­ню и мешая работать парикмахеру.

· Размещение клиента в кресле. Семафор custready обеспечивает подъем спящего парикмахера, сообщая ему о новом клиенте. Без этого семафора парикмахер никогда не отдыхал бы и приступал к стрижке немедленно по­сле того, как очередной клиент покинет кресло. При отсутствии клиента в этот момент парикмахер стриг бы воздух.

· Удержание клиента в кресле. Если уж клиент оказался в кресле, он дол­жен отсидеть там до окончания стрижки, о чем просигнализирует семафор finished.

· Ограничение количества клиентов в креслах. Семафор barber_chair предна­значен для ограничения количества клиентов в креслах — их не должно быть более трех. Однако одного семафора barber_chair для этого недостаточно. Клиент, который не получит процессорное время непосредственно после того, как парикмахер сообщит о завершении работы над его прической (вызов signal (finished)), останется в кресле (например, впав в транс или глубоко задумавшись о задаче о парикмахерской), в то время как в этом же кресле бу­дет стараться устроиться новый клиент. Для решения данной задачи использу­ется семафор leave_b_chair, который не позволяет парикмахеру пригласить нового клиента до тех пор, пока предыдущий не покинет кресло.



· Оплата стрижки. Естественно, с деньгами надо быть особенно осторожным. Кассир должен быть уверен, что каждый клиент, покидая парикмахерскую, сперва расплатится, а каждый клиент, оплатив стрижку, должен получить чек. Это достигается передачей денег кассиру из рук в руки — каждый клиент, по­кинув кресло, оплачивает услуги парикмахера, после чего дает знать об этом кассиру (вызов signal (payment)) и дожидается получения кассового чека (вызов wait (receipt)). Кассир осуществляет прием платежей, ожидая сигнала о платеже, принимая деньги, а затем сообщая об этом. Здесь следует постарать­ся избежать ряда программных ошибок. Если вызов signal (payment) выпол­няется непосредственно перед вызовом pay (), то клиент может оказаться пре­рванным в этот момент, и кассир будет пытаться принять не переданные день­ги. Еще более серьезная ошибка происходит при обмене строк signal (payment) и wait (receipt). Это может привести к взаимоблокировке всех клиентов и кассира их операциями wait.

· Координация действий кассира и парикмахера. В целях экономии средств парикмахерская не нанимает отдельного кассира. Это действие выполняет парикмахер, когда не стрижет клиента. Для того чтобы обеспечить выпол­нение парикмахером в один момент времени только одной функции, ис­пользуется семафор coord.

Семафор Операция wait Операция signal
max capacity Клиент ожидает возможности войти в парикмахерскую Клиент, покидающий парикмахер­скую, сигнализирует об этом ожи­дающему входа
sofa Клиент ожидает возможности сесть на диван Клиент, встающий с дивана, сигна­лизирует об этом ожидающему воз­можности сесть на диван
barber_chair Клиент ожидает пустое кресло Парикмахер сигнализирует, что кресло свободно
cust_ready Парикмахер ожидает, пока кли- ент сядет в кресло Клиент сигнализирует парикмахе­ру, что он уже сел в кресло
finished Клиент ожидает окончания стрижки Парикмахер сигнализирует клиен­ту, что стрижка окончена
leave_b_chair Парикмахер ожидает, пока кли­ент покинет кресло Клиент сигнализирует парикмахеру о том, что он встал с кресла
payment Кассир ожидает оплаты услуг Клиент сигнализирует кассиру о том, что он оплатил стрижку
receipt Клиент ожидает кассовый чек Кассир сигнализирует о том, что оплата принята



Листинг. Неполное решение задачи о парикмахерской.

semaphore max_capacity = 20;

semaphore sofa = 4;

semaphore barber_chair = 3;

semaphore coord = 3;

semaphore cust_ready = 0,finished - 0, leave_b_chair = 0, payment = 0, receipt = 0;

void customer()

{

wait(max_capacity);

enter_shop();

wait(sofa);

sit_on_sofa();

wait(barber_chair);

get_up_from_sofa();

signal(sofa);

sit in barber_chair();

signal(cust_ready);

wait(finished);

leave_barber_chair();

signal(leave_b_chair);

pay();

signal(payment);

wait(receipt);

exit_shop();

signal(max_capacity);

}

void barber()

{

while(true)

{

wait(cust_ready);

wait(coord);

cut_hair();

signal(coord);

signal(finished);

wait(leave_b_chair);

signal(barber_chair);

}

}

void cashier()

{

while(true)

{

wait(payment);

wait(coord);

accept_pay();

signal(coord);

signal (receipt);

}

}

void main()

{

parbegin(customer,... [50 раз] ... , customer, barber,barber,barber,cashier);

}

Процесс кассира можно устранить, внеся функцию оплаты в процедуру па­рикмахера. Каждый парикмахер будет последовательно стричь и принимать плату. Однако при наличии одного кассового аппарата необходимо ограничить доступ к функции accept_pay() одним парикмахером в каждый момент време­ни. Этого можно добиться, рассматривая функцию как критический раздел и ог­радив ее соответствующим семафором.


7965980077268099.html
7966025248490139.html
    PR.RU™