Threading is a way to run multiple threads (smaller units of process) concurrently in a single process space. Threads are lighter than processes and share the same memory space, which makes it easier and faster to communicate between threads than between processes. However, threading can be complex due to the Global Interpreter Lock (GIL) in CPython, which prevents multiple native threads from executing Python bytecodes at once.
The threading module in Python provides a way to create and manage threads. Here are the basic steps to create and run a thread:
import threading
def print_numbers():
for i in range(1, 6):
print(i)
# Create a thread
thread = threading.Thread(target=print_numbers)
# Start the thread
thread.start()
# Wait for the thread to finish
thread.join()
print("Thread finished execution")
You can also create threads by subclassing threading.Thread and overriding the run method.
import threading
class PrintNumbersThread(threading.Thread):
def run(self):
for i in range(1, 6):
print(i)
# Create and start the thread
thread = PrintNumbersThread()
thread.start()
# Wait for the thread to finish
thread.join()
print("Thread finished execution")
When multiple threads access shared data, synchronization mechanisms are needed to avoid data corruption. The threading module provides several synchronization primitives:
lock = threading.Lock()
def thread_safe_function():
with lock:
# Critical section of code
pass
2.RLock (Reentrant Lock): A lock that can be acquired multiple times by the same thread without causing a deadlock.
rlock = threading.RLock()
def reentrant_function():
with rlock:
# Critical section of code
pass
3.Semaphore: A synchronization primitive that allows a fixed number of threads to access a resource.
semaphore = threading.Semaphore(3)
def limited_access_function():
with semaphore:
# Critical section of code
pass
4.Event: A synchronization primitive that can be used to signal one or more threads to proceed
event = threading.Event()
def wait_for_event():
event.wait() # Block until the event is set
print("Event occurred")
# Create and start a thread
thread = threading.Thread(target=wait_for_event)
thread.start()
# Trigger the event
event.set()
5.Condition: A synchronization primitive that can be used to wait for some condition to be met.
condition = threading.Condition()
def wait_for_condition():
with condition:
condition.wait() # Block until notified
print("Condition met")
def notify_condition():
with condition:
condition.notify_all() # Notify all waiting threads
# Create and start threads
thread1 = threading.Thread(target=wait_for_condition)
thread2 = threading.Thread(target=notify_condition)
thread1.start()
thread2.start()