A race condition occurs when multiple processes access and manipulate shared data concurrently, and the outcome depends on the order of execution. This leads to inconsistent results.
Example: Two processes both read a counter (value=5), both increment it, and both write back. Result: 6 instead of 7.
The critical section is the part of code where shared resources are accessed. The critical section problem requires a solution that satisfies:
A software-based solution for two processes. Uses two shared variables: flag[2] (indicates intent to enter) and turn (whose turn it is).
A semaphore is an integer variable accessed only through two atomic operations: wait() (P) and signal() (V).
Binary Semaphore (Mutex): Value is 0 or 1. Used for mutual exclusion. Equivalent to a mutex lock.
Counting Semaphore: Value can be any non-negative integer. Used to control access to a resource with multiple instances.
A mutex (mutual exclusion lock) is a binary semaphore used to protect critical sections. A process must acquire the mutex before entering the critical section and release it when done.
A monitor is a high-level synchronization construct that encapsulates shared data and the procedures that operate on it. Only one process can be active inside a monitor at a time.
Producer-Consumer (Bounded Buffer): Producer adds items to a buffer; Consumer removes items. Problem: Producer must wait if buffer is full; Consumer must wait if buffer is empty. Solution: Use semaphores (empty, full, mutex).
Readers-Writers: Multiple readers can read simultaneously; writers need exclusive access. Problem: Readers may starve writers or vice versa. Solution: Use semaphores with priority rules.
Dining Philosophers: Five philosophers sit at a table with five forks. Each needs two forks to eat. Problem: All pick up left fork simultaneously -> deadlock. Solutions: Allow only 4 philosophers at a time, use asymmetric solution (odd picks left first, even picks right first), use a monitor.
Event 1: a process requests a resource related to Process
Event 2: the kernel checks permissions, availability, and current state
Event 3: the scheduler or manager decides whether to run, wait, block, or fail
Event 4: the process observes the result and continues or handles the error
Input: P1, P2, P3
Resource/state: limited
Rule: apply the Process policy step by step
Output: show which process runs, waits, completes, or is denied
Always write the before-state and after-state for each step.
The result depends on unpredictable timing between concurrent operations.
Mutual exclusion, progress, and bounded waiting.
Threads that acquire the same locks in different orders can wait on each other forever.
Explore 500+ free tutorials across 20+ languages and frameworks.