Unit 2 Os Updated
Unit 2 Os Updated
The Critical Section Problem occurs in concurrent programming when multiple processes or
threads try to access shared resources simultaneously. The goal is to ensure safe and
synchronized access to avoid race conditions and data inconsistency.
2. Structure of a Process
A solution to the critical section problem must satisfy the following conditions:
1. Mutual Exclusion: Only one process can be in the critical section at a time.
2. Progress: If no process is in the critical section, other processes should be able to enter.
3. Bounded Waiting: No process should wait indefinitely to enter the critical section.
4. Real-Time Example: Online Ticket Booking System
Imagine you are booking a movie ticket online. At the same time, another person is also trying to
book the last available seat. If there is no proper synchronization, both users may book the same
seat, causing issues.
Scenario
1. Entry Section:
o Both Process A and Process B check seat availability at the same time.
o Both processes see one available seat.
2. Critical Section (Race Condition Occurs):
o Process A selects the seat and proceeds to payment.
o Process B also selects the same seat and proceeds to payment simultaneously.
o Since both processes are in the critical section without synchronization, both
assume the seat is available.
3. Exit Section (Incorrect Behavior Occurs):
o If there is no proper synchronization, both transactions may be processed.
o The system overbooks the seat, resulting in double booking.
o This creates a conflict, requiring manual intervention or cancellation.
4. Remainder Section:
o After booking, the processes move to other tasks.
1. Locks (Mutex)
2. Semaphores
3. Atomic Transactions
Ensures that checking, selecting, and booking happen as one indivisible operation.
Example: Using a database transaction, ensuring that:
o If two users try to book the same seat, only one transaction succeeds.
4. Monitors
1. Entry Section:
o The system locks the seat when a user selects it.
2. Critical Section:
o The first user to proceed with payment gets the seat.
o The second user gets a "Seat Unavailable" message.
3. Exit Section:
o The system releases the lock after confirming the booking.
4. Remainder Section:
o The process continues for other users.
Unlike basic Test-And-Set (TAS) Locks, where a process directly releases the lock, this
algorithm checks a queue to find the next process that should enter the critical section. If no
process is waiting, the lock is set to false, allowing any new process to enter.
while (1) {
waiting[i] = true;
key = true;
j = (i + 1) % n;
if (j == i)
lock = false; // No process is waiting, release lock
else
waiting[j] = false; // Allow the next process to proceed
1. The process searches for the next waiting process in a circular queue (j = (i+1) % n).
2. It checks for a waiting process from j to n and again from 0 to i-1.
3. If a waiting process is found, it sets waiting[j] = false, allowing it to enter.
4. If no process is waiting, it sets lock = false, making the critical section available for
any future process.
Real-Life Mapping
Step Pseudocode Concept
(Printer System)
Each employee marks
1. Employees send print waiting[i] = true themselves as waiting for the
requests
printer
2. Printer lock is checked while (waiting[i] && key) key First employee to check and
using TestAndSet = TestAndSet(lock); set the lock gets the printer
3. Employee prints waiting[i] = false;
The employee now prints
document (Critical Section) the document
The system searches for the
4. Check next waiting j = (i+1) % n; next employee waiting to
employee in queue
print
5. Assigns the printer to the waiting[j] = false; The next employee in queue
next employee gets access to print
6. If no one is waiting, lock = false;
If no requests are waiting,
printer becomes free the printer is now available
ATM Withdrawals: Ensuring multiple users do not access the same ATM machine at
the same time.
Database Transactions: Ensuring multiple users do not update the same database record
simultaneously.
Traffic Signals: Managing the order of vehicles at a busy intersection to avoid collisions.
8. Conclusion
The Unlock and Lock Algorithm is an efficient hardware synchronization technique that
ensures mutual exclusion, fairness, and bounded waiting. It is widely used in operating
systems, databases, and multi-threaded applications to prevent race conditions and ensure
orderly execution of processes.
It ensures mutual exclusion, meaning that only one process can hold the lock at a time. If
another process tries to acquire the lock while it is already held, it will be blocked until the lock
is released.
Imagine two threads (T1 and T2) trying to withdraw money from a shared bank account with
an initial balance of ₹10,000:
💡 Issue: The final balance should be ₹1,000, but due to simultaneous execution without
synchronization, it is incorrectly updated to ₹6,000.
1. A thread must acquire the mutex lock before entering the critical section.
2. If another thread tries to acquire the lock while it is held, it must wait.
3. Once the thread completes its work, it releases the lock, allowing another waiting
thread to proceed.
Pseudocode:
pseudocode
Copy code
Mutex lock = 0; // 0 means available, 1 means locked
void acquire_lock() {
while (TestAndSet(&lock) == 1); // Wait until lock is free
}
void release_lock() {
lock = 0; // Unlock
}
void critical_section() {
acquire_lock(); // Enter critical section
// Perform operations
release_lock(); // Exit critical section
}
Step-by-Step Explanation
1. Initializing the Mutex Lock
pseudocode
Copy code
Mutex lock = 0;
lock = 0 → The lock is available (no thread is using the critical section).
lock = 1 → The lock is held by a thread (critical section is occupied).
🔹 Example:
After the process finishes its work, it sets lock = 0 so that other processes can enter the
critical section.
🔹 Example:
Process Initial lock Value Releases Lock? New lock Value Next Process?
P1 1 (Locked) Yes (Sets lock = 0) 0 (Free) P2 can enter
Multiple employees in an office want to print documents using a single shared printer.
If two employees try to send a print job at the same time, documents may get mixed
up.
What is a Semaphore?
A binary semaphore is a type of semaphore that can have only two values:
It is often used to implement mutual exclusion (mutex) for synchronizing access to critical
sections in a system.
2. Counting Semaphore:
A counting semaphore can have any integer value, allowing it to represent a count of available
resources. It is useful when managing a pool of identical resources (e.g., a fixed number of
printers or connections).
Let’s consider a counting semaphore S initialized to a certain value, representing the number of
available resources.
Semaphore Initialization:
pseudocode
Copy code
Semaphore S = N; // N is the number of resources (e.g., printers,
connections)
P Operation (Wait/Acquire):
pseudocode
Copy code
P(S) {
while (S <= 0) { // If no resources are available, wait
// Process will be blocked here
}
S = S - 1; // Decrease the semaphore value (resource is being used)
}
V Operation (Signal/Release):
pseudocode
Copy code
V(S) {
S = S + 1; // Increase the semaphore value (resource is released)
}
3. Real-Time Example:
Let’s consider a real-time scenario where multiple users need to access a shared printer in an
office. There are only 3 printers available, but multiple users want to use them at the same time.
Scenario:
Semaphore Initialization:
pseudocode
Copy code
Semaphore printers = 3; // 3 printers available
Steps:
Result:
At any point in time, only 3 users can print, and User D was blocked until a printer
became available. The semaphore helps synchronize access to the shared printers.
The Bounded Buffer Problem, also known as the Producer-Consumer Problem, is a classical
synchronization problem in operating systems. It involves two types of processes:
Since the buffer has a fixed size (bounded buffer), synchronization is needed to ensure that:
The producer does not add data when the buffer is full.
The consumer does not remove data when the buffer is empty.
Multiple producers and consumers do not access the buffer simultaneously in an unsafe
way.
Producer Process:
c
Copy code
do {
// Produce an item
wait(empty); // Decrement empty slots
wait(mutex); // Enter critical section
The producer checks if there is space in the buffer before adding an item.
empty keeps track of available slots, so wait(empty):
o Decrements empty by 1.
o Blocks the producer if empty == 0 (i.e., buffer is full).
Step 2: Acquire Mutex Lock (wait(mutex))
c
Copy code
wait(mutex);
Ensures mutual exclusion so only one process (either a producer or a consumer) can
modify the buffer at a time.
Prevents race conditions, where multiple processes may try to modify the buffer
simultaneously.
Example Execution
Let's assume a buffer of size N = 5 and in = 0 initially.
Consumer Process:
c
Copy code
do {
wait(full); // Decrement full slots
wait(mutex); // Enter critical section
The consumer checks if there is at least one item in the buffer before removing it.
full keeps track of occupied slots, so wait(full):
o Decrements full by 1.
o Blocks the consumer if full == 0 (i.e., buffer is empty).
Ensures mutual exclusion so only one process (producer or consumer) modifies the
buffer at a time.
Prevents race conditions, where multiple processes may try to remove items
simultaneously.
Example Execution
Let's assume a buffer of size N = 5 and out = 0 initially.
Key Takeaways
✔ Prevents buffer underflow – Consumer waits if the buffer is empty (full == 0).
✔ Ensures mutual exclusion – Only one process modifies the buffer at a time (mutex).
✔ Supports multiple producers and consumers – Uses full and empty to coordinate
operations.
✔ Uses a circular buffer – Avoids wasted space by wrapping around when out == N
Explanation of Synchronization:
How It Works:
✅ Prevents race conditions – The mutex semaphore ensures that only one process modifies the
buffer at a time.
✅ Avoids deadlock – The proper ordering of wait and signal operations prevents processes
from getting stuck.
✅ Efficient usage of buffer – Items are added and removed in a circular manner using (in + 1)
% N and (out + 1) % N.
Real-Life Example:
Readers (R): Can read the shared resource but do not modify it.
Writers (W): Can both read and modify the shared resource.
Conditions to Satisfy:
1. Multiple readers can read simultaneously (since reading does not cause inconsistency).
2. Only one writer can write at a time (to prevent data corruption).
3. While a writer is writing, no other reader or writer should access the resource.
Semaphores Used
Reader Code
c
Copy code
do {
wait(mutex); // Lock read_count
read_count++; // Increase number of readers
if (read_count == 1)
wait(wrt); // First reader blocks writers
signal(mutex); // Unlock read_count
Writer Code
c
Copy code
do {
wait(wrt); // Lock resource (only one writer at a time)
wait(mutex);
read_count--;
if (read_count == 0)
signal(wrt); // Last reader allows writers
signal(mutex);
} while (true);
7. Real-Life Examples
Databases:
o Multiple users (readers) accessing a database for viewing data.
o A writer modifies data (e.g., updating a table), requiring exclusive access.
File Systems:
o Many processes reading a file simultaneously.
o A process writing to the file must prevent reading to avoid inconsistency.
Semaphores Used
wait(mutex);
read_count--;
if (read_count == 0)
signal(wrt); // Step 7: Last reader allows writers
signal(mutex);
} while (true);
Key Idea:
This solution requires advanced data structures like condition variables or queues to maintain
fairness.
Problem Statement
A barber shop has:
One barber
One barber chair
N waiting chairs for customers who arrive when the barber is busy
Customers who arrive at random intervals
Challenges in Synchronization
Mutual Exclusion: Only one customer should occupy the barber chair at a time.
Avoiding Deadlock: If not managed properly, the barber might not wake up when a
customer arrives.
Avoiding Race Conditions: Multiple customers arriving at the same time should be
handled correctly.
Algorithm
1. Barber Process
c
Copy code
while (true) {
wait(customers); // Wait for a customer
wait(mutex); // Ensure mutual exclusion to access waiting
chairs
waiting--; // Reduce waiting count
signal(barber); // Wake up barber if needed
signal(mutex); // Release mutex
// Cut hair
}
2. Customer Process
c
Copy code
wait(mutex);
if (waiting < chairs) { // If a waiting chair is available
waiting++; // Increase waiting count
signal(customers); // Notify barber
signal(mutex); // Release mutex
wait(barber); // Wait for barber
// Get haircut
} else {
signal(mutex); // Release mutex (leave the shop)
}
Problem Statement
Imagine five philosophers sitting around a circular dining table. Each philosopher has a plate of
food in front of them and needs two chopsticks (or forks) to eat. There are only five chopsticks,
one placed between each pair of philosophers.
Since each philosopher needs two chopsticks but only one can be held at a time, the problem
leads to potential deadlockor resource starvation.
2. Using a Semaphore
If only 4 out of 5 philosophers are allowed to pick up chopsticks at a time, at least one
chopstick remains free, preventing circular wait and deadlock.
4. Odd-Even Strategy
c
Copy code
semaphore chopstick[5];
void philosopher(int i) {
while (true) {
think();
eat();
Here:
Real-World Applications
1. Process synchronization in operating systems.
2. Database management where multiple transactions need shared resources.
3. Networking and communication protocols to avoid resource deadlock.
4. Traffic management where multiple cars need access to roads.
Deadlock Prevention in Operating Systems
(Detailed Explanation)
What is a Deadlock?
A deadlock is a state in a computer system where a group of processes is stuck in a waiting
cycle, each holding a resource and waiting for another resource held by another process. This
results in an indefinite standstill where no process can make progress.
If any one of these four conditions is prevented, deadlock cannot occur. This is the principle
behind deadlock prevention.
Imagine a one-lane bridge where two cars are coming from opposite directions. Neither car can
move forward because the bridge is too narrow, and neither driver wants to reverse. The traffic
remains stuck, creating a deadlock.
Similarly, in a computer system, processes can be stuck waiting for resources held by other
processes, leading to a deadlock situation.
→ Idea: Allow multiple processes to access the resource at the same time whenever possible.
Definition: Mutual exclusion means that some resources can be used by only one process
at a time.
Prevention Approach: If possible, design resources so that multiple processes can use
them simultaneously.
Shared Files – If a file is read-only, multiple processes can read it at the same time
without needing exclusive access.
Real-Life Example:
Library Books – Instead of having a single copy of a book (which creates a mutual
exclusion problem), multiple copies are made available so that many readers can access it
at once.
❌ Limitation: Some resources, like printers or CPUs, must be used exclusively, so mutual
exclusion cannot always be avoided.
→ Idea: A process must request all required resources at once or release held resources before
requesting new ones.
Definition: Hold and wait occurs when a process is holding some resources while
waiting for others.
Prevention Approach:
o Require processes to request all resources at the start.
o If a process needs a new resource, it must release all currently held resources
and re-request everything.
When printing a document, a process should request both the printer and memory
space together rather than holding the printer and waiting for memory.
Real-Life Example:
Restaurant Order: A customer orders all required food items at once instead of keeping
a table occupied and ordering one dish at a time.
❌ Limitation:
This approach leads to resource underutilization because some resources remain idle
even when they could be used by other processes.
3. Preventing No Preemption
→ Idea: If a process holding a resource is waiting for another, the system can forcibly take
back the held resource and give it to another process.
Definition: No preemption means that once a process gets a resource, it cannot be taken
away forcibly.
Prevention Approach: If a process is holding resources but is blocked waiting for
another, the system will forcefully take away the held resources and assign them to
other processes.
CPU Scheduling: Some operating systems preempt a process’s CPU time if a higher-
priority process arrives.
Memory Allocation: If a process is waiting for more memory but is holding a printer,
the system can take the printer back and assign it to another process.
Real-Life Example:
❌ Limitation:
→ Idea: Impose an ordering rule so that processes always request resources in a predefined
sequence.
Definition: Circular wait occurs when processes form a cycle where each process waits
for a resource held by the next.
Prevention Approach: Assign a numerical order to resources and ensure that
processes always request resources in increasing order.
If a system has Scanner (R1) → Printer (R2) → Disk (R3), a process must always
request in ascending order(e.g., R1 → R2 → R3) and never in a different sequence (e.g.,
R3 → R1).
Real-Life Example:
Traffic Signal System: Vehicles follow predefined lane directions to prevent circular
traffic jams.
❌ Limitation:
Some processes may need resources in an order that does not match the predefined
sequence, leading to inefficiencies.