Introduction
In Python, multithreading and multiprocessing allow you to run multiple tasks in parallel, improving performance for certain types of programs.
While both aim to achieve parallel execution, they work differently under the hood due to Python's GIL.
Multithreading
Multithreading allows concurrent execution of multiple threads within the same process. It is best suited for I/O-bound tasks (like network requests or file operations).
Example:
import threading
import time
def print_numbers():
for i in range(5):
print(i)
time.sleep(1)
# Create threads
t1 = threading.Thread(target=print_numbers)
t2 = threading.Thread(target=print_numbers)
# Start threads
t1.start()
t2.start()
# Wait for threads to finish
t1.join()
t2.join()
print("Done")
Multiprocessing
Multiprocessing runs multiple processes, each with its own Python interpreter and memory space. It is ideal for CPU-bound tasks (like heavy computations) because it bypasses the GIL.
Example:
from multiprocessing import Process
import time
def print_numbers():
for i in range(5):
print(i)
time.sleep(1)
# Create processes
p1 = Process(target=print_numbers)
p2 = Process(target=print_numbers)
# Start processes
p1.start()
p2.start()
# Wait for processes to finish
p1.join()
p2.join()
print("Done")
Comparison: Multithreading vs Multiprocessing
| Feature | Multithreading | Multiprocessing |
|---|---|---|
| Memory | Shared memory within a process | Separate memory for each process |
| Best For | I/O-bound tasks | CPU-bound tasks |
| Performance | Limited by GIL in Python | True parallel execution |
| Overhead | Low, threads are lightweight | Higher, processes consume more resources |