Process Synchronization in OS
Process Synchronization in OS
When two or more process cooperates with each other, their order of execution must be
preserved otherwise there can be conflicts in their execution and inappropriate outputs
can be produced.
A cooperative process is the one which can affect the execution of other process or can
be affected by the execution of other process. Such processes need to be synchronized
so that their order of execution can be guaranteed.
Race Condition
When more than one process is either running the same code or modifying the same
memory or any shared data, there is a risk that the result or value of the shared data
may be incorrect because all processes try to access and modify this shared resource.
Thus, all the processes race to say that my result is correct. This condition is called
the race condition. Since many processes use the same data, the results of the
processes may depend on the order of their execution.
In order to synchronize the cooperative processes, our main task is to solve the critical
section problem. We need to provide a solution in such a way that the following
conditions can be satisfied.
The following three requirements must be met by a solution to the critical section
problem:
Semaphores
Semaphores make use of the wait() and signal() functions for synchronization among the
processes.
Binary Semaphores
Binary Semaphores can only have one of two values: 0 or 1. Because of their capacity to
ensure mutual exclusion, they are also known as mutex locks.
Hence, whenever the binary semaphore is set to 0, any process can then enter its
critical section by setting the binary semaphore to 1. When it has completed its critical
section, it can reset the binary semaphore to 0, enabling another process to enter it.
Counting Semaphores
Counting Semaphores can have any value and are not limited to a certain area. They
can be used to restrict access to a resource that has a concurrent access limit.
Counting semaphore indicates that a process can access the resource if it has a value
greater than 0. If it is set to 0, no other process can access the resource
There is a buffer of n slots and each slot is capable of storing one unit of
data. There are two processes running,
namely, producer and consumer, which are operating on the buffer.
Bounded Buffer Problem(producer Consumer problem)
do
{
// wait until empty > 0 and then decrement 'empty'
wait(empty);
// acquire lock
wait(mutex);
// 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.
do
{
// wait until full > 0 and then decrement 'full'
wait(full);
// acquire the lock
wait(mutex);
The consumer waits until there is atleast one full slot in the buffer.
Following that, the consumer completes the removal operation so that the
data from one of the full slots is removed.
Consider there are five philosophers sitting around a circular dining table.
The dining table has five chopsticks and a bowl of rice in the middle as
shown in the below figure.
From the problem statement, it is clear that a philosopher can think for an
indefinite amount of time. But when a philosopher starts eating, he has to
stop at some point of time. The philosopher is in an endless cycle of
thinking and eating.
while(TRUE)
{
wait(stick[i]);
/*
mod is used because if i=5, next
chopstick is 1 (dining table is circular)
*/
wait(stick[(i+1) % 5]);
/* 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:
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.
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);