Os Unit 3 Class Notes
Os Unit 3 Class Notes
PROCESS SYNCHRONIZATION
Process Synchronization is the coordination of execution of multiple processes in a multi-process
system to ensure that they access shared resources in a controlled and predictable manner.
It aims to resolve the problem of race conditions and other synchronization issues in a concurrent
system.
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. This condition is called the race
condition. To prevent race conditions, concurrent processes must be synchronized.
Example:
int shared = 5 // global variable
p1 p2
x = shared; y = shared;
x++; //6 y --; //4
sleep(1); sleep(1);
shared = x; //6 shared = y; //4
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 above, we need to ensure that only one process at a time can be
manipulating the variable counter.
---------------------------------------------------------------------------------------------------------------------
THE CRITICAL-SECTION PROBLEM
Mutual Exclusion
Mutual exclusion implies that only one process can be inside the critical section at any time. If
any other processes require the critical section, they must wait until it is free.
Progress
Progress means that if a process is not using the critical section, then it should not stop any other
process from accessing it.
Bounded Waiting
Bounded waiting means that each process must have a limited waiting time.
do {
entry section
critical section
remainder section
exit section
} while (1);
---------------------------------------------------------------------------------------------------------------------
PERTERSON’S SOLUTION
boolean Flag[]
The flag array is used to indicate if a process is ready to enter its critical section. For example, if flag[i] is
true, Pi is ready to enter its critical section.
int Turn:
The variable turn indicates whose turn it is to enter its critical section. For example, if turn == i, then
process Pi is allowed to execute in its critical section.
We now prove that this solution is correct. We need to show that:
To prove property 1, we note that each Pi enters its critical section only if either flag[j] == false or
turn == i.
To prove properties 2 and 3, we note that a process Pi can be prevented from entering the critical
section only if it is stuck in the while loop with the condition flag[j] == true and turn
== j; this loop is the only one possible. If Pj is not ready to enter the critical section, then flag[j] ==
false, and Pi can enter its critical section.
MUTEX LOCKS
Mutex (Mutual Exclusion) lock is a simple software tool that solves the critical section
problem.
The mutex lock is used to prevent race conditions.
A process must acquire the lock before entering a critical section; it releases the lockwhen it
exits the critical section.
The acquire() function acquires the lock, and the release() function releases the lock.
A mutex lock has a boolean variable available whose value indicates if the lock is
available or not.
If the lock is available, a call to acquire() succeeds, and the lock is then considered
unavailable.
A process that attempts to acquire an unavailable lock is blocked until the lock isreleased.
acquire() {
while (!available)
; /* busy wait */
available = false;
}
do {
acquire lock
critical section
release lock
remainder section
} while (true);
It is a synchronization tool that is used to generalize the solution to the critical section
problem.
A Semaphore S is an integer variable that can only be accessed via two indivisible (atomic)
operations namely
1. wait or P operation ( to test )
2. signal or V operation ( to increment )
Operations on a Semaphore:
wait (s)
{
while(s0);
s--;
}
signal (s)
{
s++;
}
Types of Semaphores:
1. Binary Semaphore :
o Can have only two values: 0 or 1.
o Typically used for mutual exclusion, where a semaphore of value 1 means the resource is
free, and a value of 0 means the resource is in use.
o It functions like a lock.
2. Counting Semaphore:
o Can have a value greater than 1.
o The semaphore count is the number of available resources. If the resources are added,
semaphore count automatically incremented and if the resources are removed, the count is
decremented.
Mutual Exclusion Implementation using semaphore
do
{
wait(mutex);
critical section
signal(mutex)
remainder section
} while (1);
MONITORS
A monitor is a synchronization construct that supports mutual exclusion and the ability to
wait /block until a certain condition becomes true.
A monitor is an abstract datatype that encapsulates data with a set of functions to operateon
the data.
Characteristics of Monitor
The local variables of a monitor can be accessed only by the local functions.
A function defined within a monitor can only access the local variables of a monitor and its
formal parameter.
Only one process may be active within the monitor at a time.
Syntax of a Monitor
monitor MonitorName {
shared_variable;
procedure P1() {
// Code for P1
}
procedure P2() {
// Code for P2
}
condition c;
procedure WaitForCondition() {
if (some_condition_not_met) {
c.wait(); }
}
procedure SignalCondition() {
c.signal(); }
}
The key components of monitor syntax in process synchronization are:
Shared Variables
These are variables shared by multiple processes.
Procedures/Methods: These are the functions that manipulate the shared variables. Only one process can
execute a monitor procedure at any time, ensuring mutual exclusion.
Condition Variables: These are used for synchronization. Condition variables enable processes to wait or
signal each other when certain conditions are met.
Instead of lock-based protection, monitors use a shared condition variable for synchronization
and only two operations wait() and signal() can be applied on the condition variable.
condition x, y;
x.wait (); // a process that invokes the operation is suspended.
x.signal (); //resumes one of the suspended processes(if any)
-------------------------------------------------------------------------------------------------------------------
CLASSICAL PROBLEMS OF SYNCHRONIZATION
1. Bounded-Buffer Problem
Challenges:
Allow multiple readers to access the shared resource simultaneously because they only read
the data without modifying it.
Ensure that only one writer can access the shared resource at a time to prevent data
corruption.
Ensure that no readers can read the resource while a writer is writing.
Make sure neither readers nor writers are indefinitely blocked.
The Dining Philosophers Problem
The Dining Philosophers Problem is a classic synchronization problem used to illustrate the challenges of avoiding
deadlock and starvation in concurrent programming.
Problem Description:
Imagine five philosophers seated around a circular table. Each philosopher alternates between two
states: thinking and eating.
In between each pair of philosophers is a single fork, so there are five forks in total.
To eat, a philosopher needs both the fork to their left and the fork to their right.
Philosophers can only use one fork at a time and must pick up both forks before eating. Once done,
they put down the forks and go back to thinking.
Example:
Let's name the philosophers as P1, P2, P3, P4, and P5.
P1 needs fork F1 (left) and F2 (right) to eat, P2 needs fork F2 and F3, and so on.
If all philosophers pick up their left fork at the same time, each philosopher will be holding one fork and will
be waiting for the other one, leading to deadlock.
The Barber Shop Problem is a classical synchronization problem in operating systems, similar to the
producer-consumer problem. It illustrates synchronization issues and is often solved using semaphores or
monitors.
Problem Overview:
In a barber shop:
Barber Process:
while (true)
{
wait(customerReady);
wait(mutex);
freeSeats++;
signal(barberReady);
signal(mutex);
}
Customer Process:
while (true)
{
wait(mutex);
if (freeSeats > 0) {
freeSeats--;
signal(customerReady);
signal(mutex);
wait(barberReady);
}
else {
signal(mutex);
}}
DEADLOCK
Deadlocks are a set of blocked processes each holding a resource and waiting to acquire a resource
held by another process.
Deadlock Characterization
Resource-Allocation Graph
It is a directed graph with a set of vertices V and a set of edges E.
V is partitioned into two types:
1. nodes P = {p1, p2,..pn}
2. Resource type R ={R1,R2,...Rm}
Pi -->Rj - request => request edge
Rj-->Pi - allocated => assignment edge.
Pi is denoted as a circle and Rj as a square.
Rj may have more than one instance represented as a dot within the square.
Sets P,R and E.
P = { P1,P2,P3}
R = {R1,R2,R3,R4}
E= {P1->R1, P2->R3, R1->P2, R2->P1, R3->P3 }
Resource instances
One instance of resource type R1,Two instance of resource type R2,One instance
of resource type R3,Three instances of resource type R4.
Process states
Process P1 is holding an instance of resource type R2, and is waiting for an instance of resource
type R1.
Resource Allocation Graph with a deadlock
Process P2 is holding an instance of R1 and R2 and is waiting for an instance of resource type
R3.Process P3 is holding an instance of R3.
P1->R1->P2->R3->P3->R2->P1
P2->R3->P3->R2->P2
Methods for handling Deadlocks
1. Deadlock Prevention
2. Deadlock Avoidance
3. Deadlock Detection and Recovery
------------------------------------------------------------------------------------------------------------------
Deadlock Prevention:
This ensures that the system never enters the deadlock state.
Deadlock prevention is a set of methods for ensuring that at least one of the necessary
conditions cannot hold.
By ensuring that at least one of these conditions cannot hold, we can prevent the
occurrence of a deadlock.
1. Denying Mutual exclusion
Mutual exclusion condition must hold for non-sharable resources.
Printer cannot be shared simultaneously shared by prevent processes.
Sharable resource - example Read-only files.
If several processes attempt to open a read-only file at the same time, they can be granted
simultaneous access to the file.
A process never needs to wait for a sharable resource.
If no cycle exists, then the allocation of the resource will leave the system in a safe state.
If a cycle is found, then the allocation will put the system in an unsafe state.
Banker's algorithm
Available: indicates the number of available resources of each type.
Max: Max[i, j]=k then process Pi may request at most k instances of resource type Rj
Allocation : Allocation[i. j]=k, then process Pi is currently allocated K instances of
resource type Rj
Need : if Need[i, j]=k then process Pi may need K more instances of resource type Rj