Understanding Multithreading in Python with the threading Module
This article explains Python's multithreading concepts, covering thread creation via subclassing Thread or using target functions, synchronization mechanisms like Lock, RLock, and Condition, and discusses the impact of the Global Interpreter Lock, helping readers apply threading effectively for I/O‑bound tasks.
Python is a powerful programming language widely used in many fields. Although its Global Interpreter Lock (GIL) limits true parallel computation, multithreading remains an important technique for improving the efficiency of I/O‑intensive tasks. This article delves into Python multithreading to help you use it effectively in suitable scenarios.
What is Multithreading?
A thread is the smallest unit of execution that an operating system can schedule. A process can contain multiple threads that share resources such as memory space and file handles. Multithreaded programming allows a program to execute multiple tasks seemingly in parallel, improving overall efficiency.
Python Multithreading: threading Module
Python provides the threading module for implementing multithreaded programs. This module lets you create, start, and manage threads.
1. Creating and Starting Threads:
The simplest way is to subclass threading.Thread and override the run() method, which contains the code the thread will execute.
import threading
import time
class MyThread(threading.Thread):
def __init__(self, thread_id, name, delay):
threading.Thread.__init__(self)
self.thread_id = thread_id
self.name = name
self.delay = delay
def run(self):
print(f"线程 {self.name} 开始执行")
time.sleep(self.delay) # 模拟耗时操作
print(f"线程 {self.name} 执行完毕")
# 创建线程实例
thread1 = MyThread(1, "Thread-1", 2)
thread2 = MyThread(2, "Thread-2", 3)
# 启动线程
thread1.start()
thread2.start()
# 等待线程结束 (可选)
thread1.join()
thread2.join()
print("所有线程执行完毕")2. Creating Threads Using Functions:
Another method is to use the threading.Thread class and pass the function to be executed via the target argument.
import threading
import time
def print_time(thread_name, delay):
print(f"线程 {thread_name} 开始执行")
time.sleep(delay)
print(f"线程 {thread_name} 执行完毕")
# 创建线程实例
thread1 = threading.Thread(target=print_time, args=("Thread-1", 2))
thread2 = threading.Thread(target=print_time, args=("Thread-2", 3))
# 启动线程
thread1.start()
thread2.start()
# 等待线程结束 (可选)
thread1.join()
thread2.join()
print("所有线程执行完毕")3. Thread Synchronization: Locks ( Lock and RLock )
In a multithreaded environment, multiple threads may access shared resources simultaneously, leading to data races and inconsistencies. Locks synchronize access to these resources.
threading.Lock : a basic lock; a thread must acquire it before proceeding, and other threads wait until it is released.
threading.RLock : a re‑entrant lock that allows the same thread to acquire it multiple times, but it must be released the same number of times before other threads can acquire it.
import threading
import time
counter = 0
lock = threading.Lock() # 使用 Lock
def increment_counter(thread_name):
global counter
for _ in range(100000):
lock.acquire()
try:
counter += 1
finally:
lock.release()
# 创建线程实例
thread1 = threading.Thread(target=increment_counter, args=("Thread-1",))
thread2 = threading.Thread(target=increment_counter, args=("Thread-2",))
# 启动线程
thread1.start()
thread2.start()
# 等待线程结束
thread1.join()
thread2.join()
print(f"Counter 的最终值:{counter}")4. Thread Synchronization: Condition Variable ( Condition )
A condition variable allows threads to wait until a specific condition is met and to be notified when the condition changes.
import threading
import time
condition = threading.Condition()
items = []
def produce():
condition.acquire()
for i in range(5):
time.sleep(1)
items.append(i)
print(f"生产者添加: {i}")
condition.notify() # 通知等待的消费者
condition.release()
def consume():
condition.acquire()
while True:
if not items:
print("消费者等待")
condition.wait() # 等待,直到生产者通知
item = items.pop(0)
print(f"消费者消费: {item}")
if len(items) == 0 and threading.active_count() == 2:
break # 检查线程是否运行完毕
condition.release()
# 创建线程
producer_thread = threading.Thread(target=produce)
consumer_thread = threading.Thread(target=consume)
# 启动线程
producer_thread.start()
consumer_thread.start()
# 等待线程结束
producer_thread.join()
consumer_thread.join()
print("程序结束")5. Python's GIL (Global Interpreter Lock)
Note that Python's GIL restricts the simultaneous execution of multiple threads on multi‑core CPUs. The GIL ensures that only one thread executes Python bytecode at a time, so for CPU‑bound tasks multithreading does not provide true parallelism and may even degrade performance due to context‑switch overhead.
When to Use Multithreading?
I/O‑intensive tasks: multithreading is ideal for operations that spend time waiting for I/O, such as network requests or file reads/writes.
Concurrent tasks: when you need to run multiple independent tasks simultaneously.
GUI programming: using threads for long‑running operations keeps the user interface responsive.
Conclusion
Python's multithreading provides the ability to execute tasks concurrently, especially suitable for I/O‑bound scenarios. Mastering the threading module—creating threads, synchronizing access to shared resources, and understanding the limitations of the GIL—helps you improve program efficiency. For CPU‑bound workloads, consider using the multiprocessing module to achieve true parallelism. Choosing the right concurrency tool is essential for optimal performance.
php中文网 Courses
php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.