Bird
Raised Fist0
Interview Prepoperating-systemsmediumAmazonGoogleMicrosoftTCSInfosys

Starvation vs Deadlock vs Livelock - Differences & Examples

Choose your preparation mode3 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Steps
setup

Initialize Processes and Resources

Three processes P1, P2, and P3 are created. Two resources R1 and R2 are available but not allocated. All processes start in the ready state.

💡 Setting up the initial state with all processes ready and resources free is essential to observe how resource requests lead to concurrency problems.
Line:processes = ['P1', 'P2', 'P3'] resources = {'R1': None, 'R2': None} process_states = {p: 'ready' for p in processes}
💡 Initial conditions are clear: no resource is held, no process is waiting or blocked.
📊
Starvation vs Deadlock vs Livelock - Differences & Examples - Watch the Algorithm Execute, Step by Step
Watching the processes' states and resource allocations step-by-step reveals the subtle differences between these common concurrency problems that are hard to grasp from code or definitions alone.
Step 1/10
·Active fillAnswer cell
Transition noneready - initialization
P1
ready
P2
ready
P3
ready
Ready Queue
P1P2P3
Waiting Queue
empty
🖥CPUidlet=0
Transition readyrunning pid:P1 - allocated R1
P1
running
P2
ready
P3
ready
Ready Queue
P2P3
Waiting Queue
empty
🖥CPUP1t=1
P1
Transition readyrunning pid:P2 - allocated R2
P1
running
P2
running
P3
ready
Ready Queue
P3
Waiting Queue
empty
🖥CPUP2t=2
P1
P2
Transition readywaiting pid:P3 - R1 held by P1
P1
running
P2
running
P3
waiting
Ready Queue
empty
Waiting Queue
P3 (R1)
🖥CPUP1t=3
P1
P2
P1
Transition runningwaiting pid:P1 - R2 held by P2
P1
waiting
P2
running
P3
waiting
Ready Queue
empty
Waiting Queue
P3 (R1)P1 (R2)
🖥CPUP2t=4
P1
P2
P1
P2
Transition runningwaiting pid:P2 - R1 held by P1
P1
waiting
P2
waiting
P3
waiting
Ready Queue
empty
Waiting Queue
P3 (R1)P1 (R2)P2 (R1)
🖥CPUidlet=5
P1
P2
P1
P2
idle
Transition waitingrunning pid:P3 - attempting livelock resource cycling
P1
waiting
P2
waiting
P3
running
Ready Queue
empty
Waiting Queue
P1 (R2)P2 (R1)
🖥CPUP3t=6
P1
P2
P1
P2
idle
P3
Transition waitingwaiting pid:P1 - starvation due to deadlock
P1
waiting
P2
waiting
P3
running
Ready Queue
empty
Waiting Queue
P1 (R2)P2 (R1)
🖥CPUP3t=7
P1
P2
P1
P2
idle
P3
Transition waitingwaiting pid:system - deadlock detection
P1
waiting
P2
waiting
P3
running
Ready Queue
empty
Waiting Queue
P1 (R2)P2 (R1)
🖥CPUP3t=8
P1
P2
P1
P2
idle
P3
Transition variousfinal - summary of concurrency problems
P1
waiting (starved)
P2
waiting (deadlocked)
P3
running (livelocked)
Ready Queue
empty
Waiting Queue
P1 (R2)P2 (R1)
🖥CPUP3t=9
P1
P2
P1
P2
idle
P3

Key Takeaways

Deadlock occurs when processes form a circular wait, each holding a resource the other needs.

This is hard to see from code alone because it requires visualizing resource dependencies and waiting chains.

Starvation is a form of indefinite waiting caused by unfair resource allocation or scheduling bias.

Understanding starvation requires seeing how some processes never get resources despite availability.

Livelock involves processes actively changing states and resources but making no forward progress.

Livelock is subtle because processes are not blocked but stuck in a loop of futile actions.

Practice

(1/5)
1. In which scenario is the Process Control Block (PCB) primarily used during the process state transitions in the five-state model?
easy
A. When a process moves from New to Ready state to store initial process information
B. When a process is terminated to delete all its data from memory
C. When a process is in the Ready state to execute instructions directly
D. When a process moves from Running to Waiting state to save CPU registers and state

Solution

  1. Step 1: Understand the role of PCB during state transitions

    The PCB stores the process state, CPU registers, and scheduling information during context switches.
  2. Step 2: Analyze each option

    A: PCB is created at process creation but its primary use is during context switches, not just at New to Ready.
    B: PCB is involved in termination but mainly to release resources; it is not primarily used to delete data.
    C: Processes in Ready state do not execute instructions directly; they wait for CPU allocation.
    D: Correct. When a process moves from Running to Waiting, the PCB saves CPU registers and state for resumption.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    PCB is essential for saving CPU state during Running to Waiting transitions [OK]
Hint: PCB saves CPU state during Running to Waiting transitions [OK]
Common Mistakes:
  • Thinking PCB is only used at process creation
  • Assuming Ready state processes execute instructions
  • Believing PCB is deleted immediately at termination
2. In which scenario is a Translation Lookaside Buffer (TLB) most beneficial for system performance?
easy
A. When the system uses a single-level page table with very few page faults
B. When virtual memory accesses exhibit high temporal locality of page references
C. When the system has a very small physical memory and no paging
D. When all memory accesses are sequential and predictable

Solution

  1. Step 1: Understand TLB purpose

    The TLB caches recent virtual-to-physical address translations to speed up address translation.
  2. Step 2: Analyze each option

    A: High temporal locality means repeated accesses to the same pages, so TLB hits are frequent, improving performance.
    B: Single-level page tables are fast, but TLB benefits more when page tables are large.
    C: Small physical memory with no paging reduces need for TLB since address translation is trivial.
    D: Sequential accesses may not reuse the same pages quickly, reducing TLB hit rate.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    TLB effectiveness depends on locality of reference, which is captured by when virtual memory accesses exhibit high temporal locality of page references.
Hint: TLB shines when recent translations are reused quickly [OK]
Common Mistakes:
  • Assuming TLB is always beneficial regardless of access pattern
  • Confusing physical memory size with TLB usefulness
3. Why might using semaphores alone without a mutex in a producer-consumer system lead to incorrect behavior?
medium
A. Semaphores increase memory usage exponentially without mutex
B. Semaphores cannot block threads, so busy-waiting occurs
C. Semaphores cause deadlocks if used without mutexes
D. Semaphores do not provide mutual exclusion, so concurrent buffer access can corrupt data

Solution

  1. Step 1: Role of semaphores

    Semaphores can block threads and track resource counts but do not inherently provide mutual exclusion.
  2. Step 2: Need for mutual exclusion

    Without a mutex, multiple producers or consumers can simultaneously modify the buffer, causing race conditions and data corruption.
  3. Step 3: Why other options are incorrect

    Semaphores cannot block threads, so busy-waiting occurs is false because semaphores do block; Semaphores cause deadlocks if used without mutexes is incorrect as deadlocks depend on usage, not absence of mutex; Semaphores increase memory usage exponentially without mutex is false as semaphores do not cause exponential memory growth.
  4. Final Answer:

    Option D -> Option D
  5. Quick Check:

    Semaphores synchronize counts but mutex needed for exclusive buffer access [OK]
Hint: Semaphores count resources; mutex protects critical section
Common Mistakes:
  • Assuming semaphores alone prevent race conditions
  • Confusing blocking behavior of semaphores
  • Believing mutexes cause deadlocks by default
4. Suppose a multithreaded application crashes due to a segmentation fault. Which of the following scenarios best explains why debugging is more challenging compared to a multi-process application?
hard
A. Because threads share the same memory, a fault in one thread can corrupt shared data, making root cause analysis harder
B. Because each thread has its own memory space, faults are isolated and easier to debug
C. Because thread context switches are slower, the fault is harder to reproduce
D. Because processes share memory, faults propagate easily between them

Solution

  1. Step 1: Understand memory sharing in threads

    Threads share the same address space, so a fault in one thread can corrupt shared data affecting others.
  2. Step 2: Contrast with processes

    Processes have isolated memory, so faults are contained, making debugging easier.
  3. Step 3: Evaluate options

    Because each thread has its own memory space, faults are isolated and easier to debug is false because threads share memory. Because thread context switches are slower, the fault is harder to reproduce is false; thread context switch speed does not affect fault reproducibility. Because processes share memory, faults propagate easily between them is false; processes do not share memory by default.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Shared memory in threads complicates debugging due to data corruption [OK]
Hint: Shared memory means shared bugs [OK]
Common Mistakes:
  • Assuming threads have isolated memory like processes
  • Confusing context switch speed with debugging difficulty
  • Believing processes share memory by default
5. If the buffer size in a producer-consumer system is increased dynamically at runtime, which challenge arises that the classic semaphore-based solution does NOT handle well?
hard
A. Consumers must signal the 'empty' semaphore twice per consumed item
B. The 'empty' semaphore count must be adjusted atomically to reflect new buffer slots
C. Producers will never block because buffer is always large enough
D. Mutex locks become ineffective with dynamic buffer sizes

Solution

  1. Step 1: Classic solution assumes fixed buffer size

    Semaphore 'empty' initialized once to buffer size; dynamic resizing breaks this assumption.
  2. Step 2: Adjusting semaphore counts

    When buffer grows, 'empty' semaphore must be incremented atomically to reflect new slots; otherwise, producers may block unnecessarily.
  3. Step 3: Why other options are incorrect

    Consumers must signal the 'empty' semaphore twice per consumed item is false; consumers do not signal 'empty' twice. Mutex locks become ineffective with dynamic buffer sizes is false; mutex still protects critical section regardless of size. Producers will never block because buffer is always large enough is false; producers can still block if buffer is full.
  4. Final Answer:

    Option B -> Option B
  5. Quick Check:

    Dynamic buffer size requires careful semaphore count updates [OK]
Hint: Dynamic buffer size requires dynamic semaphore adjustment
Common Mistakes:
  • Assuming fixed semaphore counts suffice for dynamic buffers
  • Thinking mutex depends on buffer size
  • Misunderstanding producer blocking conditions