Python Multithreading: Concepts, Modules, and Practical Examples
This article explains Python multithreading fundamentals, covering thread basics, the _thread and threading modules, creating and managing threads, synchronization with locks, ThreadLocal usage, thread pools, and compares multithreading with multiprocessing for CPU‑bound and I/O‑bound tasks.
Multithreading allows multiple threads to run concurrently, offering benefits such as background processing, responsive user interfaces, faster execution, and efficient resource utilization for I/O‑bound tasks.
Each thread has its own execution context, including registers like the instruction pointer and stack pointer, and can be either a kernel thread or a user thread.
Python provides two standard libraries for threading: _thread (low‑level) and threading (high‑level, recommended). The threading module includes useful functions such as threading.current_thread() , threading.enumerate() , and threading.active_count() , and the Thread class with methods like start() , run() , join() , is_alive() , getName() , and setName() .
Example of creating a simple thread with threading :
<code>import threading
import time
def print_numbers():
for i in range(5):
time.sleep(1)
print(i)
thread = threading.Thread(target=print_numbers)
thread.start()
thread.join()
</code>Creating threads using the low‑level _thread module:
<code>#!/usr/bin/python3
import _thread
import time
def print_time(threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print("%s: %s" % (threadName, time.ctime()))
try:
_thread.start_new_thread(print_time, ("Thread-1", 2))
_thread.start_new_thread(print_time, ("Thread-2", 4))
except:
print("Error: unable to start thread")
while True:
pass
</code>Thread synchronization is achieved with Lock and RLock objects, using acquire() and release() to protect shared data.
<code>import threading
import time
class MyThread(threading.Thread):
def __init__(self, threadID, name, delay):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.delay = delay
def run(self):
print("Starting thread:" + self.name)
threadLock.acquire()
print_time(self.name, self.delay, 3)
threadLock.release()
def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print("%s: %s" % (threadName, time.ctime()))
counter -= 1
threadLock = threading.Lock()
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread-2", 2)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("Main thread exiting")
</code>Thread‑local storage ( threading.local() ) provides each thread with its own independent variables, useful for per‑thread database connections or request contexts.
<code>import threading
local_school = threading.local()
def process_student():
print('Hello, %s (in %s)' % (local_school.student, threading.current_thread().name))
def process_thread(name):
local_school.student = name
process_student()
t1 = threading.Thread(target=process_thread, args=('Alice',), name='Thread-A')
t2 = threading.Thread(target=process_thread, args=('Bob',), name='Thread-B')
t1.start()
t2.start()
t1.join()
t2.join()
</code>Thread pools can be created using multiprocessing.dummy.Pool for easy management of multiple worker threads.
Comparing multithreading and multiprocessing: processes offer higher stability (a crash in one process does not affect others) but have higher creation overhead, while threads share memory and can cause the entire process to crash if one thread fails.
Task types affect concurrency strategy: CPU‑bound tasks should match the number of CPU cores, whereas I/O‑bound tasks benefit from many more threads to hide latency.
Asynchronous I/O and event‑driven models (e.g., using coroutines) allow single‑process programs to handle many I/O‑bound tasks efficiently, reducing the need for multiple threads.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
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.