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
Cause | Fix |
---|---|
High-priority threads blocking others | Use time.sleep() to release CPU |
Lock contention | Use lock.acquire(timeout=...) |
Infinite loops | Use sleep() or yield execution |
Poor scheduling | Use threading.Event() for fair execution |