Python threading Semaphore Class

The threading.Semaphore class in Python's threading module provides a way to manage a counter that is decremented each time a thread acquires the semaphore and incremented each time a thread releases it. This is useful for controlling access to a resource that has a limited capacity.

Table of Contents

  1. Introduction
  2. threading.Semaphore Class Syntax
  3. Examples
    • Basic Usage
    • Using Semaphore to Control Access to a Resource
    • Using BoundedSemaphore
  4. Real-World Use Case
  5. Conclusion

Introduction

The threading.Semaphore class is used to manage access to a resource by maintaining a counter. The counter is decremented when a thread acquires the semaphore and incremented when a thread releases it. When the counter reaches zero, any additional threads attempting to acquire the semaphore will block until the counter is incremented again.

threading.Semaphore Class Syntax

Here is how you create and use a semaphore with the threading.Semaphore class:

import threading

semaphore = threading.Semaphore(value=1)

Parameters:

  • value: The initial value of the semaphore counter. The default is 1.

Methods:

  • acquire(blocking=True, timeout=None): Decrement the counter and block if the counter is zero. If blocking is True (the default), the method will block until the counter is incremented or the optional timeout occurs. If blocking is False, the method will return immediately with True if the semaphore is acquired and False otherwise.
  • release(): Increment the counter and wake up any threads blocked on acquire().

Examples

Basic Usage

Create and use a semaphore to synchronize threads.

Example

import threading
import time

semaphore = threading.Semaphore(2)

def worker(worker_id):
    print(f"Worker {worker_id} waiting to acquire semaphore")
    with semaphore:
        print(f"Worker {worker_id} acquired semaphore")
        time.sleep(2)
        print(f"Worker {worker_id} releasing semaphore")

threads = [threading.Thread(target=worker, args=(i,)) for i in range(4)]

for thread in threads:
    thread.start()

for thread in threads:
    thread.join()

Using Semaphore to Control Access to a Resource

Use a semaphore to limit access to a resource, such as a database connection pool.

Example

import threading
import time

semaphore = threading.Semaphore(3)

def access_resource(thread_id):
    with semaphore:
        print(f"Thread {thread_id} accessing resource")
        time.sleep(1)
        print(f"Thread {thread_id} releasing resource")

threads = [threading.Thread(target=access_resource, args=(i,)) for i in range(5)]

for thread in threads:
    thread.start()

for thread in threads:
    thread.join()

Using BoundedSemaphore

Use a BoundedSemaphore to prevent the semaphore counter from exceeding its initial value.

Example

import threading
import time

semaphore = threading.BoundedSemaphore(2)

def worker(worker_id):
    print(f"Worker {worker_id} waiting to acquire semaphore")
    with semaphore:
        print(f"Worker {worker_id} acquired semaphore")
        time.sleep(2)
        print(f"Worker {worker_id} releasing semaphore")

threads = [threading.Thread(target=worker, args=(i,)) for i in range(4)]

for thread in threads:
    thread.start()

for thread in threads:
    thread.join()

Real-World Use Case

Controlling Access to a Shared Resource

Use a semaphore to control access to a shared resource, such as a printing queue or a limited number of network connections.

Example

import threading
import time

semaphore = threading.Semaphore(3)

def print_job(job_id):
    with semaphore:
        print(f"Job {job_id} is being processed")
        time.sleep(1)
        print(f"Job {job_id} is done")

jobs = [threading.Thread(target=print_job, args=(i,)) for i in range(10)]

for job in jobs:
    job.start()

for job in jobs:
    job.join()

Conclusion

The threading.Semaphore class is used for managing access to shared resources in multithreaded programs. It allows you to control the number of threads that can access a resource simultaneously, ensuring that the resource is not overwhelmed. Proper usage can significantly enhance the reliability and efficiency of your concurrent applications.

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare