Classical Problem Notes'
Classical Problem Notes'
Bounded buffer problem, which is also called producer consumer problem, is one of the
classic problems of synchronization. Let's start by understanding the problem here, before
moving on to the solution and program code.
A producer tries to insert data into an empty slot of the buffer. A consumer tries to remove
data from a filled slot in the buffer. As you might have guessed by now, those two
processes won't produce the expected output if they are being executed concurrently.
There needs to be a way to make the producer and consumer work in an independent
manner.
Here's a Solution
One solution of this problem is to use semaphores. The semaphores which will be used
here are:
empty, a counting semaphore whose initial value is the number of slots in the buffer,
At any instant, the current value of empty represents the number of empty slots in the buffer
and full represents the number of occupied slots in the buffer.
// release lock
signal(mutex);
// increment 'full'
signal(full);
}
while(TRUE)
Looking at the above code for a producer, we can see that a producer first waits until
there is atleast one empty slot.
Then it decrements the empty semaphore because, there will now be one less empty
slot, since the producer is going to insert data in one of those slots.
Then, it acquires lock on the buffer, so that the consumer cannot access the buffer until
producer completes its operation.
After performing the insert operation, the lock is released and the value of full is
incremented because the producer has just filled a slot in the buffer.
The consumer waits until there is atleast one full slot in the buffer.
Then it decrements the full semaphore because the number of occupied slots will be
decreased by one, after the consumer completes its operation.
After that, the consumer acquires lock on the buffer.
Following that, the consumer completes the removal operation so that the data from one
of the full slots is removed.
Then, the consumer releases the lock.
Finally, the empty semaphore is incremented by 1, because the consumer has just
/* eat */
signal(stick[i]);
signal(stick[(i+1) % 5]);
/* think */
}
When a philosopher wants to eat the rice, he will wait for the chopstick at his left and picks up
that chopstick. Then he waits for the right chopstick to be available, and then picks it too. After
eating, he puts both the chopsticks down.
But if all five philosophers are hungry simultaneously, and each of them pickup one chopstick,
then a deadlock situation occurs because they will be waiting for another chopstick forever. The
possible solutions for this are:
A philosopher must be allowed to pick up the chopsticks only if both the left and right
chopsticks are available.
Allow only four philosophers to sit at the table. That way, if all the four philosophers pick up
four chopsticks, there will be one chopstick left on the table. So, one philosopher can start
eating and eventually, two chopsticks will be available. In this way, deadlocks can be
avoided.
The Solution
From the above problem statement, it is evident that readers have higher priority than writer. If a
writer wants to write to the resource, it must wait until there are no readers currently accessing
that resource.
Here, we use one mutex m and a semaphore w. An integer variable read_count is used to
maintain the number of readers currently accessing the resource. The variable read_count is
initialized to 0. A value of 1 is given initially to m and w.
Instead of having the process to acquire lock on the shared resource, we use the mutex m to make
the process to acquire and release lock whenever it is updating the read_count variable.
The code for the writer process looks like this:
while(TRUE)
{
wait(w);
signal(w);
}
And, the code for the reader process looks like this:
while(TRUE)
{
//acquire lock
wait(m);
read_count++;
if(read_count == 1)
wait(w);
//release lock
signal(m);
// acquire lock
wait(m);
read_count--;
if(read_count == 0)
signal(w);
// release lock
signal(m);
}
Here is the Code uncoded(explained)
As seen above in the code for the writer, the writer just waits on the w semaphore until it gets a
After performing the write operation, it increments w so that the next writer can access the
resource.
On the other hand, in the code for the reader, the lock is acquired whenever the read_count is
updated by a process.
When a reader wants to access the resource, first it increments the read_count value, then accesses
The semaphore w is used by the first reader which enters the critical section and the last reader
The reason for this is, when the first readers enters the critical section, the writer is blocked from
the resource. Only new readers can access the resource now.
Similarly, when the last reader exits the critical section, it signals the writer using the w semaphore
because there are zero readers now and a writer can have the chance to access the resource.