Process Synchronization
Process Synchronization
Synchronization
Common Synchronization Problems
Race Condition: A race condition occurs when two or more processes (or threads) access shared
data simultaneously and the outcome depends on the order of execution.
Deadlock: Deadlock occurs when two or more processes are each waiting for the other to release
a resource, causing the system to freeze.
Starvation: happens when a process is perpetually denied access to a resource because other
processes are continuously favored
Producer Consumer
Problem
Before Starting an explanation of code, first, understand the few terms used in
the above code:
4.count is further divided into 3 lines code represented in the block in both
the producer and consumer code.
Producer Consumer Problem Cont.
int count = 0;
void producer(void)
{
Producer Code
int itemP;
while(1)
{ If we talk about Producer code first:
Produce_item(item P)
while(count == n); --Rp is a register which keeps the value
buffer[in] = item P; of m[count]
in = (in + 1)mod n
count = count + 1; --Rp is incremented (As element has
} been added to buffer)
}
--an Incremented value of Rp is stored
Memory Management back to m[count]
Load Rp, m[count]
Increment Rp
Store m[count], Rp
Producer Consumer Problem Cont.
int count;
void consumer(void)
{ Consumer Code
int itemC;
while(1) Similarly, if we talk about Consumer code
{ next:
while(count == 0);
itemC = buffer[ out]; --Rc is a register which keeps the value of
out = (out + 1) mod n; m[count]
count = count - 1;
} --Rc is decremented (As element has been
} removed out of buffer)
Load Rc, m[count] → will copy count value which is 5 to register Rp.
function signal(S):
function wait(S): // This function represents the 'signal' or 'release'
// This function represents the 'wait' operation for a semaphore.
operation for a semaphore.
if there are processes sleeping on S:
if S > 0: // Wake up a blocked process
// Do not block the process select a process to wake up
S <- S - 1 wake up the selected process
return return
else: else:
// Block the calling process // No process is waiting on S
sleep S <- S + 1
return
There are two types of semaphores:
● Binary semaphore
● Counting Semaphore
A binary semaphore can have only two integer values: 0 or 1. It’s simpler to implement and
provides mutual exclusion. We can use a binary semaphore to solve the critical section problem.
Some experienced readers might confuse binary semaphores with a mutex. There’s a common
misconception that they can be used interchangeably. But in fact, a semaphore is a signaling
mechanism where on the other hand, a mutex is a locking mechanism. So, we need to know that
binary semaphore is not a mutex.
A deadlock occurs when a
group of processes is
blocked in a state waiting
for some other member’s
action.
process P[i]
while true do
{
THINK;
PICKUP(CHOPSTICK[i], CHOPSTICK[i+1 mod 5]);
EAT;
PUTDOWN(CHOPSTICK[i], CHOPSTICK[i+1 mod 5])
}
Var successful: boolean;
repeat
successful:= false;
if left neighbor is waiting for
while (not successful)
his right fork
if both forks are available then
then
lift the forks one at a time;
activate (left neighbor);
successful:= true;
if right neighbor is waiting for
if successful = false his left fork
then then
block(Pi); activate( right neighbor);
{eat} {think}
forever
put down both forks;
In this solution, when philosopher
decides to eat, it first waits on semaphore
. Then after acquiring it, the philosopher
waits on semaphore . When both
chopsticks are acquired, it can eat.
When the philosopher is full, it releases
the chopsticks in the same order, by
calling the signal operation on the
respective semaphore.
One common solution to the Dining Philosopher Problem uses semaphores, a
synchronization mechanism that can be used to control access to shared
resources.
If a philosopher cannot acquire both semaphores, they must wait until they
become available.
semaphores forks[n] = {1, 1, 1, ..., 1}; // All forks are available initially
mutex := Semaphore(1); // Mutex for critical section