
📌Multithreading in Python with Example:
Use Python’s Thread
class to handle multiple threads running in the background with minimal code.
Python multithreading is crucial for building scalable applications that handle multiple requests simultaneously.
Python multithreading allows concurrent execution of tasks, making your applications faster and more responsive.
Learn how to use Python’s threading
module to build lightweight, multi-threaded programs efficiently.
Despite Python’s Global Interpreter Lock (GIL), multithreading is powerful for I/O-bound operations.”
Boost your app’s performance by mastering Python multithreading for tasks like web scraping and file handling.
Python threading is ideal for parallel execution of functions without creating separate processes.
🧵 What is a Thread?
A thread is a unit of execution within a process. Multithreading allows a CPU to execute multiple threads concurrently, often resulting in better performance for I/O-bound applications.
⚙️ What is a Process?
A process is an instance of a program in execution. When you launch an application, your operating system creates a process that includes code, data, and system resources.
🧠 What is Multithreading in Python?
Multithreading in Python lets you run multiple threads within the same process. Threads share memory, making communication between them easier. However, Python threads are best suited for I/O-bound tasks due to the limitations of the GIL.
🔄 Multithreading vs Multiprocessing:
Feature | Multithreading | Multiprocessing |
---|---|---|
Threads/Processes | Multiple threads | Multiple processes |
Memory Usage | Low (shared memory) | High (separate memory) |
Ideal For | I/O-bound tasks | CPU-bound tasks |
GIL Impact | Yes | No |
🧰 Multithreading in Python with Example Python Threading Modules:
Python provides two modules for multithreading:
- _thread: Low-level and deprecated (use only for learning purposes).
- threading: High-level, recommended for production.
⚠️ Using the _thread Module (Deprecated):
pythonimport time
import _thread
def thread_test(name, wait):
for i in range(4):
time.sleep(wait)
print(f"Running {name}")
print(f"{name} has finished execution")
if __name__ == "__main__":
_thread.start_new_thread(thread_test, ("First Thread", 1))
_thread.start_new_thread(thread_test, ("Second Thread", 2))
_thread.start_new_thread(thread_test, ("Third Thread", 3))
time.sleep(10) # Ensures main thread waits for child threads
This demonstrates basic thread execution, but lacks safety features like synchronization.
✅ Using the threading Module (Recommended):
pythonimport time
import threading
class ThreadTester(threading.Thread):
def __init__(self, name, wait):
super().__init__()
self.name = name
self.wait = wait
def run(self):
for i in range(5):
time.sleep(self.wait)
print(f"Running {self.name}")
print(f"{self.name} has finished execution")
if __name__ == "__main__":
t1 = ThreadTester("First Thread", 1)
t2 = ThreadTester("Second Thread", 2)
t3 = ThreadTester("Third Thread", 3)
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
This version uses OOP with the threading.Thread
class, offering better control and thread safety.
⚠️ Deadlocks and Race Conditions:
💥 Race Condition Example
pythoni = 0
def increment():
global i
for _ in range(100000):
i += 1
# Spawning multiple threads that modify `i` can lead to inconsistent results.
🔒 Deadlock Example:
Occurs when two threads wait indefinitely for each other to release locks.
🔐 Synchronizing Threads with Locks:
pythonimport threading
lock = threading.Lock()
def safe_print(name):
for _ in range(5):
lock.acquire()
print(f"{name} is running")
lock.release()
if __name__ == "__main__":
t1 = threading.Thread(target=safe_print, args=("Thread-1",))
t2 = threading.Thread(target=safe_print, args=("Thread-2",))
t1.start()
t2.start()
t1.join()
t2.join()
Using locks avoids inconsistent outputs by ensuring only one thread prints at a time.
🧠 What is GIL in Python?
The Global Interpreter Lock (GIL) is a mutex in CPython that allows only one thread to execute Python bytecode at a time. This prevents race conditions in memory management but limits true multithreading for CPU-bound tasks.
💡 How GIL Affects Execution:
- In I/O-bound programs, the GIL doesn’t cause much trouble.
- In CPU-bound programs, the GIL prevents parallel execution, even on multi-core systems.
✅Multithreading in Python with Example Solution:
For CPU-bound tasks, use the multiprocessing
module instead of multithreading to bypass GIL restrictions.
📌Multithreading in Python with Example Summary:
- Multithreading lets Python run multiple threads but is limited by the GIL.
- Use
threading.Thread
for high-level thread management. - Use
Lock
,RLock
,Semaphore
, etc., to handle race conditions. - For CPU-bound tasks, prefer
multiprocessing
. - The GIL exists to protect memory management but limits multithreaded performance in CPU-heavy programs.