Critical section, semaphores, mutex, and deadlock handling
Concurrency Control - Managing shared resources safely
Critical Section: Code that accesses shared resources
Entry Section → Request permission
Critical Section → Access shared resource
Exit Section → Release permission
Remainder Section → Non-critical code
| Requirement | Description |
|---|---|
| Mutual Exclusion | Only one process in CS at a time |
| Progress | If CS empty, selection can't be postponed indefinitely |
| Bounded Waiting | Limit on how long a process waits |
# Binary lock: locked (1) or unlocked (0)
mutex = 1
def acquire():
while mutex == 0:
pass # busy wait
mutex = 0 # lock it
def release():
mutex = 1 # unlock it
# Usage
acquire()
# ... critical section ...
release()
# Counting semaphore: can be > 1
# Binary semaphore: 0 or 1 (like mutex)
class Semaphore:
def __init__(self, value):
self.value = value
def wait(self): # P operation
while self.value <= 0:
pass
self.value -= 1
def signal(self): # V operation
self.value += 1
# Producer-Consumer Example
empty = Semaphore(n) # n empty slots
full = Semaphore(0) # 0 full slots
mutex = Semaphore(1) # mutual exclusion
# Producer
empty.wait()
mutex.wait()
# add item to buffer
mutex.signal()
full.signal()
# Consumer
full.wait()
mutex.wait()
# remove item from buffer
mutex.signal()
empty.signal()
| Mutex | Semaphore |
|---|---|
| Binary (0/1) | Counting (0 to n) |
| Ownership (same thread unlocks) | No ownership |
| For mutual exclusion | For synchronization + ME |
Producer: Creates items, adds to buffer
Consumer: Removes items from buffer
Buffer: Fixed size (n slots)
Issues to handle:
- Producer waits if buffer full
- Consumer waits if buffer empty
- Only one accesses buffer at a time
Multiple readers can read simultaneously
Only one writer at a time
No reader while writing, no writer while reading
Solution: Use mutex for writers, allow multiple readers
5 philosophers, 5 forks
Each needs 2 forks to eat
Can cause deadlock if all pick left fork first
Solutions:
- Allow only 4 to sit
- Pick both forks atomically
- Odd picks left first, even picks right first
Deadlock: Set of processes blocked, each waiting for resource held by another
| Condition | Description |
|---|---|
| Mutual Exclusion | Resource held by only one process |
| Hold and Wait | Process holds resource while waiting for another |
| No Preemption | Resources can't be forcibly taken |
| Circular Wait | Circular chain of processes waiting |
Process → Resource: Request edge
Resource → Process: Assignment edge
Deadlock if cycle exists (single instance per resource)
P1 → R1 → P2 → R2 → P1 ← DEADLOCK!
| Condition | Prevention |
|---|---|
| Mutual Exclusion | Make resources sharable (not always possible) |
| Hold and Wait | Request all resources at once |
| No Preemption | Allow preemption |
| Circular Wait | Order resources, request in order |
System checks if granting request leads to safe state
Safe state: Can complete all processes in some order
Banker's Algorithm:
- Available: Resources currently available
- Max: Maximum each process may need
- Allocation: Currently allocated
- Need = Max - Allocation
Safe sequence example:
Available = [3, 3, 2]
Can P1 finish? Need[P1] <= Available?
If yes, allocate, let finish, reclaim resources
Continue until all processes finish
Detection: Find cycles in resource graph
Recovery options:
- Terminate deadlocked processes
- Preempt resources
- Rollback to checkpoint
Ignore the problem!
Used when deadlock is rare and detection is expensive
Most OSes (Windows, Linux) use this approach
| Concept | Key Point |
|---|---|
| Critical Section | Needs mutual exclusion |
| Mutex | Binary lock with ownership |
| Semaphore | Counting, P(wait) and V(signal) |
| Deadlock conditions | ME, Hold-Wait, No-Preempt, Circular |
| Banker's Algorithm | Safe state = can finish all |
| Prevention | Break one condition |
Test your understanding with step-by-step solutions
10 questions · 90s per question
Each question has a 90-second time limit. Unanswered questions will be auto-submitted when time runs out.