1. Critical Section Problem
🎯 Interview Key Point: Critical Section is a code segment where processes access shared resources. Only ONE process should execute in critical section at a time.
Critical Section Visualization
Process Structure:
do {
// Entry Section
// CRITICAL SECTION
// Exit Section
// Remainder Section
} while (true);
Real Example: Bank ATM withdrawal - Only one person can access account balance at a time to prevent incorrect deductions.
Requirements for Critical Section Solution:
- Mutual Exclusion: Only one process in CS at a time
- Progress: If no process in CS, selection cannot be postponed
- Bounded Waiting: Limit on waiting time
2. Race Condition
⚠️ Problem: When multiple processes access shared data simultaneously, final result depends on execution order.
Process 1
→
Shared
Data
←
Process 2
Example Race Condition:
Shared variable: counter = 0
Process 1: Process 2:
counter = counter + 1 counter = counter + 1
Expected: counter = 2
Actual: counter = 1 (Race condition!)
🎯 Interview Tip: Always explain race condition with bank account example - two people withdrawing money simultaneously.
3. Solutions to Race Condition
Solution |
Description |
Pros |
Cons |
Atomic Operations |
Execute in single CPU cycle |
Fast, No waiting |
Limited operations |
Mutex/Locks |
Binary lock mechanism |
Simple to implement |
Deadlock possible |
Semaphores |
Counter-based synchronization |
Multiple resources |
Complex implementation |
4. Mutex/Locks
Mutex Working
Mutex Pseudocode:
acquire(lock)
while (lock == 1)
wait; // Busy waiting
lock = 1;
release(lock)
lock = 0;
// Usage
acquire(lock);
// Critical Section
release(lock);
Mutex Problems:
- Busy Waiting: Process wastes CPU cycles
- Deadlock: Processes wait for each other
- Starvation: High priority threads blocked
5. Conditional Variables
🎯 Key Concept: Condition variables solve busy waiting problem. Thread sleeps until condition is met.
Condition Variable Operations:
wait(condition, lock)
// Release lock and sleep
// Wake up when signaled
// Reacquire lock
signal(condition)
// Wake up one waiting thread
broadcast(condition)
// Wake up all waiting threads
Producer-Consumer Example:
Producer waits if buffer full
Consumer waits if buffer empty
No busy waiting - threads sleep when condition not met
6. Semaphores
Semaphore Concept
Semaphore Operations:
wait(S) / P(S) / down(S)
while (S <= 0)
wait; // Block process
S--;
signal(S) / V(S) / up(S)
S++;
wakeup(blocked_process);
Type |
Range |
Use Case |
Binary Semaphore |
0 or 1 |
Mutex (single resource) |
Counting Semaphore |
0 to N |
Multiple identical resources |
Example: Parking lot with 10 spaces
Semaphore S = 10
Car enters: wait(S) → S = 9
Car exits: signal(S) → S = 10
7. Dining Philosophers Problem
5 Philosophers Around Table
Semaphore Solution:
semaphore fork[5] = {1,1,1,1,1};
philosopher(i) {
while(true) {
think();
wait(fork[i]); // Pick left fork
wait(fork[(i+1)%5]); // Pick right fork
eat();
signal(fork[i]); // Put left fork
signal(fork[(i+1)%5]); // Put right fork
}
}
Deadlock Problem: All philosophers pick left fork simultaneously → All wait for right fork → DEADLOCK!
Deadlock Prevention Solutions:
Solution 1: Allow only 4 philosophers to sit
Solution 2: Pick both forks atomically
Solution 3: Odd philosophers pick left first, even pick right first
Asymmetric Solution:
philosopher(i) {
if (i % 2 == 0) {
wait(fork[(i+1)%5]); // Even: right first
wait(fork[i]); // then left
} else {
wait(fork[i]); // Odd: left first
wait(fork[(i+1)%5]); // then right
}
eat();
signal(fork[i]);
signal(fork[(i+1)%5]);
}
8. Common Interview Questions
Q1: What is race condition?
Answer: When multiple processes access shared resource simultaneously and final result depends on execution timing.
Q2: Difference between Mutex and Semaphore?
Answer: Mutex is binary (0/1), Semaphore can be counting. Mutex for single resource, Semaphore for multiple resources.
Q3: How to prevent deadlock in dining philosophers?
Answer: Use asymmetric solution - odd philosophers pick left first, even pick right first.
Q4: What is busy waiting?
Answer: Process continuously checks condition in loop, wasting CPU cycles. Solved by condition variables.