Thread starvation in multithreading

Loading

Thread starvation occurs when some threads are unable to execute because other high-priority threads continuously consume CPU time, preventing lower-priority threads from making progress. This can lead to system slowdown or deadlock.


1. Causes of Thread Starvation

A. High-Priority Threads Blocking Lower-Priority Threads

When high-priority threads dominate CPU time, lower-priority threads may never get scheduled.

Example

import threading
import time

def high_priority():
while True: # Keeps running, preventing other threads from executing
print("High-priority thread running...")

def low_priority():
while True:
print("Low-priority thread running...")
time.sleep(1) # Allows other threads some execution time

thread1 = threading.Thread(target=high_priority, daemon=True) # High priority
thread2 = threading.Thread(target=low_priority, daemon=True) # Low priority

thread1.start()
thread2.start()

time.sleep(5)

Issue: The high-priority thread runs indefinitely, preventing the low-priority thread from executing.

Fix: Use time.sleep() or threading.Lock() to ensure fair execution.

def high_priority():
while True:
print("High-priority thread running...")
time.sleep(0.1) # Gives other threads a chance to execute

B. Resource Starvation (Lock Contention)

If multiple threads compete for the same resource (e.g., a Lock), some threads may be starved if they cannot acquire the lock.

Example (Causing Thread Starvation)

lock = threading.Lock()

def worker_1():
while True:
with lock:
print("Worker 1 acquired lock")

def worker_2():
while True:
with lock:
print("Worker 2 acquired lock")

thread1 = threading.Thread(target=worker_1)
thread2 = threading.Thread(target=worker_2)

thread1.start()
thread2.start()

Issue: If one thread holds the lock too long, the other thread gets starved.

Fix: Use lock.acquire(timeout=...) to prevent starvation.

def worker():
while True:
if lock.acquire(timeout=1): # Avoid indefinite waiting
print(f"{threading.current_thread().name} acquired lock")
time.sleep(0.5)
lock.release()
else:
print(f"{threading.current_thread().name} could not acquire lock")

C. Infinite Loops in Threads

A thread running an infinite loop without yielding execution time can starve other threads.

Fix: Add time.sleep() to release CPU time

while True:
print("Thread running...")
time.sleep(0.1) # Allows other threads to execute

D. Poor Thread Scheduling

Some operating systems may not fairly schedule threads, leading to starvation.

Fix: Use threading.Event() for better synchronization.

event = threading.Event()

def worker():
while not event.is_set():
print("Worker executing...")
time.sleep(1)

thread = threading.Thread(target=worker)
thread.start()

time.sleep(5)
event.set() # Stops the worker after 5 seconds

2. Summary of Fixes

CauseFix
High-priority threads blocking othersUse time.sleep() to release CPU
Lock contentionUse lock.acquire(timeout=...)
Infinite loopsUse sleep() or yield execution
Poor schedulingUse threading.Event() for fair execution

Leave a Reply

Your email address will not be published. Required fields are marked *