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
- Introduction
threading.Semaphore
Class Syntax- Examples
- Basic Usage
- Using Semaphore to Control Access to a Resource
- Using BoundedSemaphore
- Real-World Use Case
- 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. Ifblocking
isTrue
(the default), the method will block until the counter is incremented or the optional timeout occurs. Ifblocking
isFalse
, the method will return immediately withTrue
if the semaphore is acquired andFalse
otherwise.release()
: Increment the counter and wake up any threads blocked onacquire()
.
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
Post a Comment
Leave Comment