0% found this document useful (0 votes)
7 views9 pages

OS UNIT-2 Remaining Part 2

The document discusses the producer-consumer problem, a classic synchronization issue involving cooperating processes where a producer generates data consumed by a consumer, requiring synchronization to prevent race conditions. It outlines solutions using semaphores for various synchronization problems, including the dining philosophers, readers-writers, and sleeping barber problems, emphasizing the need for mutual exclusion and avoiding deadlock. The document also highlights the importance of managing shared resources and ensuring proper access control to prevent starvation and race conditions.

Uploaded by

Yuvika Miglani
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views9 pages

OS UNIT-2 Remaining Part 2

The document discusses the producer-consumer problem, a classic synchronization issue involving cooperating processes where a producer generates data consumed by a consumer, requiring synchronization to prevent race conditions. It outlines solutions using semaphores for various synchronization problems, including the dining philosophers, readers-writers, and sleeping barber problems, emphasizing the need for mutual exclusion and avoiding deadlock. The document also highlights the importance of managing shared resources and ensuring proper access control to prevent starvation and race conditions.

Uploaded by

Yuvika Miglani
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

UNIT-2nd Concurrent Process

Producer-Consumer Problem:

To illustrate the concept of cooperating processes, let's consider the producer-consumer problem, which is
a common paradigm for cooperating processes. A producer process produces information that is
consumed by a consumer process.
One solution to the producer-consumer problem uses shared memory. To allow producer and
consumer processes to run concurrently, we must have available a buffer of items that can be filled by the
producer and emptied by the consumer. The producer and consumer must be synchronized, so that the
consumer does not try to consume an item that has not yet been produced.
To solve this problem let’s take the bounded buffer. The bounded buffer assumes a fixed buffer
size. In this case, the consumer must wait if the buffer is empty, and the producer must wait if the buffer
is full.
The following variables reside in a region of memory shared by the producer and consumer
processes:

The shared buffer is implemented as a circular array with two logical pointers: in and out.
The variable in points to the next free position in the buffer and the variable out points to the first full
position in the buffer. The buffer is empty when in = = out and the buffer is full when ((in+ 1) %
BUFFER_SIZE) = = out.

/* The Producer Process */

/* The Consumer Process */

1
This scheme allows at most BUFFER_SIZE - 1 items in the buffer at the same time.
To overcome the limitation of BUFFER_SIZE – 1, we add an integer variable counter, which is initialized
to 0. Counter is incremented every time we add a new item to the buffer and is decremented every time we
remove one item from the buffer. The code for the producer process can be modified as follows:

/* The Producer Process */

The code for the consumer process can be modified as follows:

/* The Consumer Process */

2
Although both the producer and consumer routines shown above are correct separately, they may not
function correctly when executed concurrently. As an illustration, suppose that the value of the variable
counter is currently 5 and that the producer and consumer processes execute the statements "counter++"
and "counter--" concurrently. Following the execution of these two statements, the value of the variable
counter may be 4, 5, or 6! The only correct result, though, is counter == 5, which is generated correctly if
the producer and consumer execute separately.
Statement" counter++" may be implemented in machine language as:

register1 = counter
register1 = register1 + 1
counter= register1

Where register1 is one of the local CPU registers. Similarly, the statement register2"counter--" is
implemented as follows:

register2 = counter
register2 = register2 - 1
counter= register2

The concurrent execution of "counter++" and "counter--" is equivalent to a sequential execution such as:

T0: producer execute register1 =counter {register1 = 5}


T1: producer execute register1 = register1 + 1 {register1 = 6}
T2: consumer execute register2 = counter {register2 = 5}
T3: consumer execute register2 = register2 - 1 {register2 = 4}
T4: producer execute counter= register1 {counter = 6}
T5: consumer execute counter = register2 {counter = 4}

Notice that we have arrived at the incorrect state "counter= =4", indicating that four buffers are full,
when, in fact, five buffers are full. If we reversed the order of the statements at T4 and T5, we would
arrive at the incorrect state "counter= = 6".

A situation like this, where several processes access and manipulate the same data concurrently and the
outcome of the execution depends on the particular order in which the access takes place, is called a race
condition. To guard against the race condition, we need to ensure that only one process at a time can be
manipulating the variable counter, i.e; the process must be synchronized in some way.

Classical Problems Of Synchronization


The Bounded-Buffer Problem (Producer/Consumer Problem)

We assume that buffer size is n. The solution to this problem requires three semaphores. These
semaphores are full, mutex and empty.

full  This semaphore counts the number of full slots in buffer.


empty  This semaphore counts the number of empty slots in buffer.
mutex  This semaphore is used to provide mutual exclusion, that both producer and consumer do not
access the buffer at the same time.

3
Mutex is initialized to value, empty is initialized to value n, and full is initialized to value 0.

# define buffercapacity n
typedef int semaphore;
semaphore full = 0;
semaphore empty = buffercapicity;
semaphore mutex = 1;

/* structure of the producer process */

do{
…..
// produce an item
……
wait(empty); // decrement the empty semaphore
wait(mutex); // enter critical section
……
// put item to the buffer
……
signal(mutex); // leave critical section
signal(full); // increment the full semaphore
}
/* structure of the consumer process */
do{
wait(full); // decrement the full semaphore
wait(mutex); // enter critical section
…..
// remove an item from buffer
…..
signal(mutex); // leave critical section
signal(empty); // increment the empty semaphore
……
// consume the item
} while(TRUE);
The Dining-Philosophers problem

 Five philosophers sit around a circular table. Each philosopher spends his life alternatively
thinking and eating. In the center of the table is a large plate of food. The philosophers can only
afford five chopsticks. One chopstick is placed between each pair of philosophers and they agree
that each will only use the chopstick to his immediate right and left.
 The problem is to design a set of processes for philosophers such that each philosopher can eat
periodically and none dies for hunger. A philosopher to the left or right of a dining philosophers
4
cannot eat while the dining philosopher is eating, since forks are shared resources.

 Solution to this problem using semaphore can be implemented as:


Each philosopher picks up his right chopstick before he tried to pick up his left chopstick.
A philosopher tries to grab a chopstick by executing a wait () operation on that
semaphore; he releases his chopstick by executing the signal operation on the appropriate
semaphore.

/* Shared Data */

Semaphore chopstick[5]; // All the elements of chopstick are initialized to 1.

5
/* Structure of philosopher i */

Although this solution guarantees that no two neighbors are eating simultaneously, but it could
create a deadlock.
Suppose that all five philosophers become hungry simultaneously and each grabs her
left chopstick. All the elements of chopstick will now be equal to 0. When each philosopher tries
to grab her right chopstick, she will be delayed forever.
Some possible solutions to overcome the deadlock problem are:
1. Allow at most four philosophers to be sitting simultaneously at the table.
2. Allow a philosopher to pick up his chopsticks only if both chopsticks are available.
3. Use an asymmetric solution; that is, an odd philosopher picks up first his left chopstick
and then his right chopstick, whereas an even philosopher picks up his right chopstick
and then his left chopstick.

The Reader-Writer Problem

Suppose that a database is to be shared among several concurrent processes. Some of these processes may
want only to read the database, whereas others may want to update (that is, to read and write) the
database.
We distinguish between these two types of processes by referring to the former as readers and
to the latter as writers. Obviously, if two readers access the shared data simultaneously, no adverse effects
will result. However, if a writer and some other process (either a reader or a writer) access the database
simultaneously, chaos may ensue.
To ensure that these difficulties do not arise, we require that the writers have exclusive access
to the shared database while writing to the database. This synchronization problem is referred to as the
readers-writers problem.

The readers-writers problem has two variations, all involving priorities.

 Readers have priority over writers


 Writers have priority over readers

NOTE: In most solutions, the non-priority group can starve. A solution to either problem may result in
starvation. In the first case, writers may starve; in the second case, readers may starve.

6
Solution to readers-writers problem with readers have priority over writers

/* Shared data structures */

semaphore mutex, wrt;


int readcount;

/* The structure of the writers process */

/* The structure of the readers process */

Reader-writer locks are most useful in the following situations:

 In applications where it is easy to identify which processes only read shared data and which
processes only write shared data.
 In applications that have more readers than writers. This is because reader-writer locks generally
require more overhead to establish than semaphores or mutual-exclusion locks. The increased
concurrency of allowing multiple readers compensates for the overhead involved in setting up the
reader-writer lock.

7
Sleeping Barber Problem

Consider a barber’s shop where there is only one barber, one barber chair and a number of waiting chairs
for the customers. When there are no customers the barber sits on the barber chair and sleeps. When a
customer arrives he awakes the barber or waits in one of the vacant chairs if the barber is cutting someone
else’s hair. When all the chairs are full, the newly arrived customer simply leaves.

Problems
 There might be a scenario in which the customer ends up waiting on a barber and a barber waiting
on the customer, which would result to a deadlock.
 Then there might also be a case of starvation when the customers don’t follow an order to cut
hair, as some people won’t get a haircut even though they had been waiting long.

The solution to these problems involves the use of three semaphores out of which one is a mutex (binary
semaphore). They are:
 Customers: Helps count the waiting customers.
 Barber: To check the status of the barber, if he is idle or not.
 accessSeats: A mutex which allows the customers to get exclusive access to the number of free
seats and allows them to increase or decrease the number.
 NumberOfFreeSeats: To keep the count of the available seats, so that the customer can either
decide to wait if there is a seat free or leave if there are none.

The Procedure

 When the barber first comes to the shop, he looks out for any customers i.e. calls P(Customers), if
there are none he goes to sleep.
 Now when a customer arrives, the customer tries to get access to the accessSeats mutex i.e. he
calls P(accessSeats), thereby setting a lock.
 If no free seat (barber chair and waiting chairs) is available he releases the lock i.e. does a
V(accessSeats) and leaves the shop.
 If there is a free seat he first decreases the number of free seats by one and he calls V(Customers)
to notify the barber that he wants to cut.
 Then the customer releases the lock on the accessSeats mutex by calling V(accessSeats).
 Meanwhile when V(Customers) was called the barber awakes.
 The barber locks the accessSeats mutex as he wants to increase the number of free seats available,
as the just arrived customer may sit on the barber’s chair if that is free.
 Now the barber releases the lock on the accessSeats mutex so that other customers can access it to
the see the status of the free seats.
 The barber now calls a V(Barber), i.e. he tells the customer that he is available to cut.
 The customer now calls a P(Barber), i.e. he tries to get exclusive access of the barber to cut his
hair.
 The customer gets a haircut from the barber and as soon as he is done, the barber goes back to
sleep if there are no customers or waits for the next customer to alert him.
 When another customer arrives, he repeats the above procedure again.
 If the barber is busy then the customer decides to wait on one of the free waiting seats.
 If there are no customers, then the barber goes back to sleep.

8
Implementation

The following pseudo-code guarantees synchronization between barber and customer and is deadlock
free, but may lead to starvation of a customer.

/* shared variables */

Semaphore Customers = 0;
Semaphore Barber = 0;
Mutex accessSeats = 1;
int NumberOfFreeSeats = N; // total number of seats

/* The Barber Process */

while (true) {
P(Customers) // tries to acquire a customer - if none is available he goes to sleep
P(accessSeats) // at this time he has been awaken - want to modify the number of
available seats(mutex protect the no of available seats)
NumberOfFreeSeats++ // one chair gets free
V(Barber) // the barber is ready to cut
V(accessSeats) // we don't need the lock on the chairs anymore(release the mutex on
the chairs)
……….. // here the barber is cutting hair
}

/* The Customer Process */

P(accessSeats) // tries to get access to the chairs(mutex protect the no.


of available seats)
if (NumberOfFreeSeats > 0) { // if there are any free seats
NumberOfFreeSeats-- // sitting down on a chair
V(Customers) // notify the barber, that there is a customer waiting
V(accessSeats) // don't need to lock the chairs anymore(release the lock)
P(Barber) // now it's this customers turn, but wait if the barber is busy
……… // here the customer is having his hair cut
}
else
{
// there are no free seats
V(accessSeats) // release the lock on the seats
…….. // customer leaves without a haircut
}
Note: The solution can be modified so that the customers are made to form a queue as they arrive so that
the barber can service these customers on a first come first served basis. This solves the problem of
starvation where in a customer might have to wait long for his turn to come.

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy