0% found this document useful (0 votes)
17 views7 pages

EXP6

experimnet 6

Uploaded by

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

EXP6

experimnet 6

Uploaded by

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

Experiment No.

Introduction
One of the classic synchronization problems is the bounded buffer problem, commonly known as
the producer-consumer problem. In this blog, we'll look at the Producer-Consumer problem,
which is used to synchronize many processes. Before we move on to the solution and program
code, let's first examine the problem.

Producer-Consumer Problem
In the producer-consumer problem, there is one Producer who produces things, and there is
one Consumer who consumes the products which are produced by the producer. The producers
and consumers share the same fixed-size memory buffer.

The Producer's role is to produce data, store it in the buffer, and then generate data again. The
Consumer's task is to consume the data from the buffer.

The Producer-Consumer problem is a classic multi-process synchronization problem, which


implies we're aiming to synchronize many processes.

When the consumer is consuming an item from the buffer, the producer should not add items
into the buffer, and vice versa. As a result, only one producer or consumer should access the
buffer at a time. This scenario seems to be a problem, let’s discuss all the scenarios which can
cause problems to the system.

What's the problem here?

Let's consider that there are n slots in the buffer, and each slot may store one unit of data. On the
buffer, there are two processes running: producer and consumer.
A producer tries to fill an empty space in the buffer with data. A consumer attempts to retrieve
data from that buffer slot. If those two processes run concurrently, as you may have anticipated,
they will not give the desired outcome.

There must be a method to make both the producer and the customer operate independently.

The following are some of the issues that might arise in the Producer-Consumer:

● The producer should generate data only if the buffer is not full. When the buffer is filled,
the producer should not be able to add any more data to it.
● When the buffer is not empty, the consumer can consume the data. The consumer should
not be able to take any data from the buffer if it is empty.
● The buffer should not be used by both the producer and the consumer at the same time.

What’s the solution then?


Semaphores can be used to solve the three difficulties listed above. A semaphore S is an integer
variable with just two standard operations: wait() and signal().

The signal() method increases the value of semaphore by one, whereas the wait() operation
decreases it by one.

wait(S){
while(S<=0); // busy waiting in the while loop
S--; // decreasing S by one
}

signal(S){
S++; // increasing S by one
}

There are two types of semaphores:

Binary Semaphore - This is related to, but not the same as, a mutex lock. It can only have two
possible values: 0 and 1. Its value is set to 1 at the start. It is used to implement a solution to a
critical section problem including multiple processes.

Counting Semaphore - Its value can traverse an unbounded domain. It's used to limit who has
access to a resource with numerous instances.

To solve this problem, We employ three semaphore variables:-

● mutex - The lock is acquired and released using a mutex, a binary semaphore.
● empty - empty is a counting semaphore that is initialized on the basis of the number of
slots present in the buffer, at first all the slots are empty.
● full - a counting semaphore with a value of zero as its starting value.
At any particular time, the current value of empty denotes the number of vacant slots in the
buffer, while full denotes the number of occupied slots.

The Producer Solution

The pseudocode for the producer function will look like this:

do
{
// process will wait until the empty > 0 and further decrement of 'empty'
wait(empty);
// To acquire the lock
wait(mutex);

/* Here we will perform the insert operation in a particular slot */

// To release the lock


signal(mutex);
// increment of 'full'
signal(full);
}
while(TRUE)

● When we look at the above code for a producer, we can see that it first waits until at least
one slot is vacant.
● wait(empty) decreases the value of the semaphore variable "empty" by one, indicating
that when the producer produces anything, the value of the empty space in the buffer
decreases. If the buffer is full, or the value of the semaphore variable "empty" is 0, the
program will stop and no production will take place.
● wait(mutex) sets the semaphore variable "mutex" to zero, preventing any other process
from entering the critical section.
● The buffer is then locked, preventing the consumer from accessing it until the producer
completes its function.
● signal(mutex) is being used to mark the semaphore variable "mutex" to "1" so that other
processes can arrive into the critical section though because the production is finished
and the insert operation is also done.
● So, After the producer has filled a slot in the buffer, the lock is released.
● signal(full) is utilized to increase the semaphore variable "full" by one because after
inserting the data into the buffer, one slot is filled in the buffer and the variable "full"
must be updated.

This is how we address the producer section of the producer-consumer problem.

The Consumer Solution


The pseudocode for the producer function will look like this:

do
{
// need to wait until full > 0 and then decrement the 'full'
wait(full);
// To acquire the lock
wait(mutex);

/* Here we will perform the remove operation in a particular slot */

// To release the lock


signal(mutex);
// increment of 'empty'
signal(empty);
}
while(TRUE);

● The consumer waits until the buffer has at least one full slot.
● wait(full) is used to reduce the semaphore variable "full" by one since the variable "full"
must be reduced by one of the consumers consuming some data.
● wait(mutex) sets the semaphore variable "mutex" to "0", preventing any other processes
from entering the critical section.
● And soon after that, the consumer then acquires a lock on the buffer.
● The consumer then completes the data removal operation by removing data from one of
the filled slots.
● So because the consumption and remove operations are complete, signal(mutex) is being
used to set the semaphore variable "mutex" to "1" so that other processes can enter the
critical section now.
● The lock is then released by the consumer.
● Because one slot space in the buffer is released after extracting the data from the buffer,
signal(empty) is used to raise the variable "empty" by one.

This is how we overcome the producer-consumer problem.

Frequently Asked Questions


Why do we use semaphores to solve the producer-consumer problem?

Mutual exclusion is ensured via the mutex semaphore. We can solve our problem by employing
the three semaphore variables, as well as the wait() and signal() functions (the wait() method
reduces the semaphore variable by one, while the signal() function helps by increasing the
semaphore variable by one).
How many counting semaphores are used?

There are two counting semaphores used, first is “empty”, which is initialized on the basis of the
number of slots present in the buffer. And the second is “full”, which is initialized with a value
zero as its starting value.

What is the main cause of the producer-consumer problem?

A producer attempts to fill an empty buffer space with data. A consumer tries to get data from
that buffer slot. If you execute those two procedures at the same time, as you may expect, you
won't get the intended result. And this situation leads to the famous producer-consumer problem.

__________________________________________________________

#include <stdio.h>
#include <stdlib.h>
int full=0,empty=10,mutex=1,x=0;
void producer()
{
++full;
empty=empty-1;
mutex=mutex-1;
x++;
printf("\nproducer produces item %d",x);
mutex=mutex+1;
}
void consumer()
{
--full;
mutex=mutex-1;
empty=empty+1;
printf("\nconsumer consumes item %d",x);
x--;
mutex=mutex+1;
}
int main()
{
int n,choice;

printf("1. producer");
printf("\n2. consumer");
printf("\n3. exit");
do{
printf("\nenter your choice");
scanf("%d",&choice);
switch(choice)
{
case 1:
if(mutex==1 && empty!=0)
{
producer();
}
else
{
printf("buffer is full");
}

break;
case 2:
if(mutex==1 && full!=0)
{
consumer();
}
else
{
printf("buffer is empty");
}
break;
default: exit(0);
break;
}
}while(choice<=3);

return 0;
}

You might also like