0
0
PythonHow-ToBeginner · 4 min read

How to Use Semaphore in Python for Thread Control

In Python, use threading.Semaphore to limit the number of threads accessing a resource simultaneously. Create a semaphore with a count, then use acquire() to enter and release() to exit the critical section.
📐

Syntax

The threading.Semaphore class controls access to a shared resource by multiple threads. You create it with an initial count that sets how many threads can access the resource at once.

  • semaphore = threading.Semaphore(value): Creates a semaphore with a given count.
  • semaphore.acquire(): Decreases the count by one, blocking if count is zero until another thread releases.
  • semaphore.release(): Increases the count by one, allowing other threads to acquire.
python
import threading

# Create a semaphore allowing 3 threads at once
semaphore = threading.Semaphore(3)

# Acquire the semaphore (decrement count)
semaphore.acquire()

# Release the semaphore (increment count)
semaphore.release()
💻

Example

This example shows 5 threads trying to access a resource, but only 2 can enter at the same time because the semaphore count is 2. Each thread waits 2 seconds inside the critical section.

python
import threading
import time

def worker(semaphore, thread_id):
    print(f"Thread {thread_id} waiting to enter")
    semaphore.acquire()
    print(f"Thread {thread_id} entered")
    time.sleep(2)  # Simulate work
    print(f"Thread {thread_id} leaving")
    semaphore.release()

semaphore = threading.Semaphore(2)
threads = []

for i in range(5):
    t = threading.Thread(target=worker, args=(semaphore, i+1))
    threads.append(t)
    t.start()

for t in threads:
    t.join()
Output
Thread 1 waiting to enter Thread 2 waiting to enter Thread 3 waiting to enter Thread 4 waiting to enter Thread 5 waiting to enter Thread 1 entered Thread 2 entered Thread 1 leaving Thread 3 entered Thread 2 leaving Thread 4 entered Thread 3 leaving Thread 5 entered Thread 4 leaving Thread 5 leaving
⚠️

Common Pitfalls

Common mistakes when using semaphores include:

  • Not releasing the semaphore after acquiring it, causing deadlocks.
  • Using a semaphore count that is too high or too low for the resource limits.
  • Forgetting that acquire() blocks the thread if the count is zero, which can freeze your program if not handled.

Always use try-finally or context managers to ensure release() is called.

python
import threading

semaphore = threading.Semaphore(1)

# Wrong way: forgetting to release
semaphore.acquire()
# ... do work
# semaphore.release()  # Missing release causes deadlock

# Right way: always release
semaphore.acquire()
try:
    # ... do work
    pass
finally:
    semaphore.release()
📊

Quick Reference

Remember these key points when using threading.Semaphore:

  • Initialize with the max number of threads allowed.
  • Use acquire() before entering the critical section.
  • Use release() after leaving to free the slot.
  • Use try-finally to avoid deadlocks.

Key Takeaways

Use threading.Semaphore to limit concurrent thread access to resources.
Always pair acquire() with release() to avoid deadlocks.
Semaphore count controls how many threads can enter simultaneously.
Use try-finally blocks to ensure release() is called even if errors occur.
Semaphore.acquire() blocks if no slots are available, so plan accordingly.