Sunteți pe pagina 1din 8

(1) The Sleeping Barber Problem.

A barbershop has a single room with one barber chair and n customer
chairs. Customers (i.e., independent processes) enter the waiting room one at a time if empty chairs are
available, otherwise they go elsewhere. Each time the barber (i.e., an independent process) finishes a
haircut the customer leaves to go elsewhere, and, among the waiting customers, the one who has been
waiting the longest (i.e., a FIFO waiting queue) moves to the barber’s chair to get a haircut. If the barber
discovers that the waiting room is empty, (s)he falls asleep in the waiting room. An arriving customer
finding the barber asleep wakes the barber (i.e., a rendezvous takes place) and has a haircut; otherwise
the arriving customer waits. Using semaphores and shared variables only (but not critical region
statements or monitors), give two algorithms, one for the barber, and another for an arbitrary customer,
that implement the sleeping barber problem. Explain your algorithms, and explicitly specify any
assumptions you make about the model.

var semaphore mutex := 1;


semaphore wlist := 1; // counting semaphore. Customers wait FIFO on this semaphore.
semaphore hcut := 0; // barber does the haircutting on this semaphore
semaphore sleep := 0; // barber sleeps on this semaphore
semaphore done: := 0; // customers are lined up on this semaphore.
int ncustomers := 0; // The number of waiting customers on wlist semaphore
bool busy := False; // Indicates whether the barber is busy or sleeping.

Barber:
repeat
wait (mutex);
if (ncustomers = 0)
then begin // no waiting customers. Get ready to sleep.
signal (mutex);
wait (sleep); // sleep until awakened by a customer.
busy := True;
wait (hcut); // Do the haircut until the customer is satisfied.
busy := False; // Done with the haircut
signal (done); // Synch with multiple streaming customers.
end
else begin
signal (wlist); // Release the earliest customer.
signal (mutex);
busy := True;
wait (hcut); // do the haircut until the customer is satisfied.
busy := False; // Done with the haircut
end
until False;
Customer:

wait (mutex);
if ((ncustomers = 0) and not busy )
then begin // Barber is sleeping
signal (sleep); // Awaken the barber
signal (mutex);
GET-HAIRCUT;
signal (hcut); // Satisfied with the haircut; release the barber.
wait (done); // This is the only barrier in this part of the code that prevents
// multiple streaming customers to be synched with the barber.
end // Done with the haircut.
else if ( ncustomers = n)
then signal (mutex); // No room in the shop. Go away.
else begin // Barber is busy; prepare to wait.
ncustomers := ncustomers + 1;
signal (mutex);
wait (wlist); // go into the waiting list.
GET-HAIRCUT;
wait (mutex);
ncustomers := ncustomers –1;
signal (hcut); // release barber after the haircut
signal (mutex);
end; // Done with the haircut; go away.
(2) The Sleeping Barber Problem With Multiple Barbers: Revise the above problem into the following
version (this is a real example from my barbershop): There are two barbers (Tina and Judy) and two
barber chairs. Customers entering the shop declare three preferences: Tina, Judy or “don’t-care”.
Waiting customers will still be serviced FIFO (i.e., the system satisfies the fairness and the liveness
properties) with the exception of (a) those waiting for Tina will decline when Judy is available and wait
for Tina in a FIFO order, and (b) those waiting for Judy will decline when Tina is available and wait for
Judy in a FIFO order. Using semaphores and shared variables only (but not critical region statements or
monitors), give five algorithms, one for each barber, and three for each customer type, that implement
the sleeping barber problem with two barbers.
Explain your algorithms, and explicitly specify any assumptions you make about the model.

var semaphore mutex := 1;


semaphore Twlist := 1; // Tina’s waiting list. Counting semaphore.
semaphore Thcut := 0; // Tina cuts hair
semaphore Tsleep := 0; // Tina sleeps
semaphore Tdone := 0; // Tina-streaming customer synchronization
int Tcustomers := 0; // Count of customers waiting for Tina
boolean Tbusy := False; // Indicates whether Tina is busy cutting hair or not.
int Tpid; // process id of the customer getting haircut from Tina.

semaphore Jwlist := 1; // Judy’s waiting list. Counting semaphore.


semaphore Jhcut := 0; // Judy cuts hair
semaphore Jsleep := 0; // Judy sleeps
semaphore Jdone := 0; // Judy-streaming customer synchronization
int Jcustomers := 0; // Count of customers waiting for Judy
boolean Jbusy := False; // Indicates whether Judy is busy cutting hair or not.
int Jpid; // process id of the customer getting haircut from Judy.

semaphore dwlist : = 1; // Don’t-Care waiting list. Counting semaphore.


int Dcustomers := 0; // Count of Don’t-Care waiting customers.

Linked-list LIST := NULL; // Linked-list of all waiting customers (of Tina, Judy or
// Don’t-Care). Contains a character (“T”, “J” or “D”) and
// and the process id (pid) of the waiting customer.
// Linked-list manipulation procedures:
void AddList (linked-list A, enum Type, int self-pid); // Adds an element with
// <Type, self-pid) to the end of the linked-list A.
char LocateEarliestTorDCustomerType (linked-list A); // Locates the type of earliest
// type “T” or “D” customer.
int LocateEarliestTorDCustomerPid (linked-list A); // Locates the pid of earliest
// type “T” or “D” customer.
char LocateEarliestJorDCustomerType (linked-list A); // Locates the type of earliest
// type “J” or “D” customer.
int LocateEarliestJorDCustomerPid (linked-list A); // Locates the pid of earliest
// type “J” or “D” customer.
void DeleteEarliestCustomerTorD (linked-list A); // Deletes earliest “T” or “D” customer.
void DeleteEarliestCustomerJorD (linked-list A); // Deletes earliest “J” or “D” customer.
Barber Tina:
repeat
wait(mutex);
if ((Tcustomers + Dcustomers) = 0)
then begin // No customers waiting for Tina.
signal (mutex);
wait (Tsleep); // Tina sleeps
Tbusy := True;
wait (Thcut); // Do the haircut until customer is satisfied.
Tbusy := False;
signal (done); // Sync with the customer.
end
else begin // There are waiting customers.
char Tnext := LocateEarliestTorDCustomerType (LIST); // Decide T or D to awaken?
Tpid := LocateEarliestTorDCustomerPid (LIST); // Pid of customer to awaken.
DeleteEarliestCustomerTorD (LIST); // Delete the chosen customer from the
if (Tnext = “T”) // waiting list.
then begin
Tcustomers := Tcustomers –1;
Tbusy := True;
signal (mutex);
signal (Twlist); // Release the “T” customer for the haircut.
wait (Thcut); // Do the haircut until the customer is satisfied.
Tbusy := False;
signal (Tdone); //Done with the haircut; Synch with customer.
end
else begin
Dcustomers := Dcustomers –1;
Tbusy := True;
signal (mutex);
signal (Dwlist); // Release the “D” customer for the haircut.
wait (Thcut); // Do the haircut until the customer is satisfied.
Tbusy := False;
end
until False;
TCustomer:
….
// self-pid (int) is the process id of the customer.
wait (mutex);
if ((Tcustomers + Dcustomers) = 0 and not Tbusy)
then begin // No waiting T or D customers and Tina is sleeping.
signal (Tsleep); // Awaken Tina
signal (mutex);
GET T-HAIRCUT;
signal (Thcut); // Haircut done.
wait (Tdone); // Synch with Tina.
end
else if ((Tcustomers + Jcustomers + Dcustomers)=n)
then signal (mutex); // No room in the barbershop. Go away.
else begin // Prepare to wait for Tina.
Tcustomers := Tcustomers + 1;
AddList (LIST, “T”, self-pid);
signal (mutex);
wait (Twlist); // Wait for Tina.
GET T-HAIRCUT;
signal (Thcut); // Done with the haircut. Release Tina for housekeeping work.
end;
// Done with the haircut. Go away.
DCustomer:
….
// self-pid (int) is the process id of the customer.
wait (mutex);
if ((Tcustomers + Dcustomers) = 0 and not Tbusy)
then begin // No waiting T or D customers and Tina is sleeping.
signal (Tsleep); // Awaken Tina
signal (mutex);
GET T-HAIRCUT;
signal (Thcut); // Haircut done.
wait (Tdone); // Synch with Tina.
end
else if ((Jcustomers + Dcustomers) = 0 and not Jbusy)
then begin // No waiting J or D customers and Judy is sleeping.
signal (Jsleep); // Awaken Judy
signal (mutex);
GET J-HAIRCUT;
signal (Thcut); // Haircut done.
wait (Jdone); // Synch with Judy.
end
else if ((Tcustomers + Jcustomers + Dcustomers)=n)
then signal (mutex); // No room in the barbershop. Go away.
else begin // Both Tina and Judy are busy. Prepare to wait.
Dcustomers := Dcustomers + 1;
AddList (LIST, “D”, self-pid);
signal (mutex);
wait (Dwlist); // Wait for Tina or Judy.
GET HAIRCUT; // This haircut may be by Tina or Judy; we don’t know.
if (self-pid = Tpid )
then signal (Thcut); // Release Tina.
else signal (Jhcut); // Release Judy.
end;
// Done with the haircut. Go away.
…..
(3) The Savings Account Problem. A savings account is shared by several people (i.e., processes). Each
person may deposit or withdraw funds from the account. The current balance in the account is the sum
of all deposits to date minus the sum of all withdrawals to date. The balance must never become
negative, and withdrawals are serviced First-Come-First-Serve with one twist: Those who want to
withdraw money from the account are desperate (students?) to get their money; so, if the balance is not
sufficient, they wait (in a FIFO order) until somebody else deposits enough money for them to make
their withdrawals. Note that those waiting for others to deposit (so that they can withdraw) are serviced
strictly FIFO. For example, suppose the current balance is 200 dollars, and customer A is waiting to
withdraw 300 dollars. Assume another customer, say B, arrives with the request of withdrawing 200
dollars. Customer B must wait until customer A is serviced. Using semaphores (but not conditional
critical region statements, critical region statements or monitors), give the algorithms for customers to
withdraw or deposit funds. Explain your algorithms, and explicitly specify any assumptions you make
about the model.

var semaphore mutex := 1;


semaphore wlist := 1; // Customers wait FIFO on this semaphore to withdraw.
int wcount := 0; // The number of waiting withdrawal customers on wlist
int balance := 500;
linked-list LIST := NULL; // The list containing the withdrawal requests of
// waiting customers.
// Linked-list manipulation procedures:
void AddEndOfList (linked-list A, int Val); // Adds an element with value Val
to the end of the linked-list A.
void DeleteFirstRequest (linked-list A); // Deletes the first element in list A.
int FirstRequestAmount (linked-list A); //Returns the value in the first element in list A.

Depositing Customer:
// Assume that the local variable deposit (int) contains the amount to be deposited.
wait (mutex);
balance := balance + deposit;
if (wcount = 0)
then signal (mutex); // no withdrawal requests at this time.
else if (FirstRequestAmount (LIST) > balance )
then signal (mutex); // Still not enough balance for the first waiting withdrawal request.
else signal (wlist); // Release the earliest waiting customer. Note that mutex is released
// by the withdrawal customer—to avoid race conditions.
// Deposit has taken place.
….
Withdrawing Customer:
// Assume that the local variable withdraw (int) contains the amount to be withdrawn.
wait (mutex);
if (wcount = 0 and balance > withdraw)
then begin // Enough balance to withdraw.
balance := balance – withdraw;
signal (mutex);
end
else begin // Either other withdrawal requests are waiting or not enough balance.
AddEndOf List (LIST, withdraw);
wcount := wcount + 1;
signal (mutex);
wait (wlist); // Dtart waiting for a deposit
balance := balance – FirstRequestAmount (LIST); // Withdraw.
DeleteFirstRequest (LIST); // Remove own request from the waiting list.
wcount := wcount – 1;
signal (mutex); // This signal() is paired with the depositing customers wait()
end; // Withdrawal is completed.
// Withdrawal is completed.

S-ar putea să vă placă și