Python threading Module
Python’s threading module is one of the standard libraries for implementing multi-threaded programming. Multi-threading allows a program to execute multiple tasks at the same time, improving the program’s efficiency and responsiveness.
The threading module provides tools for creating and managing threads, allowing developers to easily write concurrent programs.
What is a Thread?
Section titled “What is a Thread?”You can think of a thread as an employee in an office:
-
A single-threaded program is like having only one employee who must complete all tasks sequentially — printing documents, replying to emails, making coffee, etc.
-
A multi-threaded program is like having multiple employees who can simultaneously work on different tasks, greatly improving work efficiency.
In computer science:
- Process: A running program with its own independent memory space (e.g., your browser and music player running simultaneously are two processes).
- Thread: An independent execution flow within a process, and the basic unit of CPU scheduling. All threads within the same process share the process’s memory space (such as global variables).
Why Use Multi-threading?
Section titled “Why Use Multi-threading?”In single-threaded programs, tasks are executed sequentially one after another. If a task needs to wait (e.g., waiting for a network response or file read), the entire program is blocked until that task completes. Multi-threading allows the program to continue executing other tasks while waiting for one task, thereby improving the overall performance of the program.
Python Threads and the Global Interpreter Lock (GIL)
Section titled “Python Threads and the Global Interpreter Lock (GIL)”Python has a mechanism called the Global Interpreter Lock (GIL). The GIL ensures that only one thread can execute Python bytecode at any given time.
What does this mean? For CPU-intensive tasks (such as scientific computing, image processing), due to the GIL, multi-threading typically cannot take advantage of multi-core benefits to improve computation speed, and may even become slower due to the overhead of thread switching.
So, where does Python multi-threading shine? For I/O-intensive tasks (such as network requests, reading/writing files, waiting for user input), threads release the GIL while waiting for I/O operations to complete, allowing other threads to run. This can significantly improve the overall responsiveness and efficiency of the program, because while waiting for a web page response, the program can handle another task.
How to Use the threading Module?
Section titled “How to Use the threading Module?”The first step in using the threading module is to import it:
The most basic way to create a thread is to use the threading.Thread class.
Syntax Description:
- target: Specifies the function to execute after the thread starts.
- args: Arguments passed to the target function, which must be a tuple type. If there is only one argument, it needs to be written as
(arg,).
1. Creating Threads
Section titled “1. Creating Threads”In Python, you can create threads by inheriting the threading.Thread class or directly using the threading.Thread constructor.
Method 1: Inheriting the threading.Thread Class
Section titled “Method 1: Inheriting the threading.Thread Class”Example
Section titled “Example”Method 2: Using the threading.Thread Constructor
Section titled “Method 2: Using the threading.Thread Constructor”Example
Section titled “Example”2. Thread Synchronization
Section titled “2. Thread Synchronization”In multi-threaded programming, multiple threads may simultaneously access shared resources, which can lead to data inconsistency issues. To avoid this, you can use thread synchronization mechanisms, such as locks (Lock).
Example
Section titled “Example”3. Inter-Thread Communication
Section titled “3. Inter-Thread Communication”Inter-thread communication can be achieved through queues (Queue). Queue is thread-safe and can safely pass data between multiple threads.
Example
Section titled “Example”Common Classes, Methods, and Attributes
Section titled “Common Classes, Methods, and Attributes”1. Core Classes
Section titled “1. Core Classes”| Class/Method/Attribute | Description | Example |
|---|---|---|
threading.Thread |
Thread class for creating and managing threads | t = Thread(target=func, args=(1,)) |
threading.Lock |
Mutex lock (primitive lock) | lock = Lock() |
threading.RLock |
Reentrant lock (same thread can acquire multiple times) | rlock = RLock() |
threading.Event |
Event object for thread synchronization | event = Event() |
threading.Condition |
Condition variable for complex thread coordination | cond = Condition() |
threading.Semaphore |
Semaphore for controlling concurrent thread count | sem = Semaphore(3) |
threading.BoundedSemaphore |
Bounded semaphore (prevents count from exceeding initial value) | b_sem = BoundedSemaphore(2) |
threading.Timer |
Timer thread for delayed execution | timer = Timer(5.0, func) |
threading.local |
Thread-local data (independent storage per thread) | local_data = threading.local() |
2. Common Methods/Attributes of the Thread Object
Section titled “2. Common Methods/Attributes of the Thread Object”| Method/Attribute | Description | Example |
|---|---|---|
start() |
Start the thread | t.start() |
run() |
Method executed by the thread (can be overridden) | Override in custom class |
join(timeout=None) |
Block the current thread until the target thread ends | t.join() |
is_alive() |
Check if the thread is running | if t.is_alive(): |
name |
Thread name (modifiable) | t.name = "Worker-1" |
daemon |
Daemon thread flag (auto-exits when main thread exits) | t.daemon = True |
ident |
Thread identifier (None if not started) |
print(t.ident) |
3. Common Methods of Lock/RLock
Section titled “3. Common Methods of Lock/RLock”| Method | Description | Example |
|---|---|---|
acquire(blocking=True, timeout=-1) |
Acquire the lock (blocking or non-blocking) | lock.acquire() |
release() |
Release the lock | lock.release() |
locked() |
Check if the lock is held | if not lock.locked(): |
4. Common Methods of Event
Section titled “4. Common Methods of Event”| Method | Description | Example |
|---|---|---|
set() |
Set the event to true, waking all waiting threads | event.set() |
clear() |
Reset the event to false | event.clear() |
wait(timeout=None) |
Block until the event is true or timeout | event.wait(2.0) |
is_set() |
Check the event status | if event.is_set(): |
5. Common Methods of Condition
Section titled “5. Common Methods of Condition”| Method | Description | Example |
|---|---|---|
wait(timeout=None) |
Release the lock and block until notified or timeout | cond.wait() |
notify(n=1) |
Wake up to n waiting threads |
cond.notify(2) |
notify_all() |
Wake up all waiting threads | cond.notify_all() |
6. Module-Level Functions/Attributes
Section titled “6. Module-Level Functions/Attributes”| Function/Attribute | Description | Example |
|---|---|---|
threading.active_count() |
Return the number of currently active threads | print(threading.active_count()) |
threading.current_thread() |
Return the current thread object | print(threading.current_thread().name) |
threading.enumerate() |
Return a list of all active threads | for t in threading.enumerate(): |
threading.main_thread() |
Return the main thread object | if threading.current_thread() is threading.main_thread(): |
threading.get_ident() |
Return the current thread’s identifier (Python 3.3+) | print(threading.get_ident()) |
Examples
Section titled “Examples”1. Basic Thread Creation
Example
Section titled “Example”2. Using Locks to Protect Shared Resources
Example
Section titled “Example”3. Event Synchronization
Example
Section titled “Example”4. Producer-Consumer Model (Condition)
Example
Section titled “Example”Important Notes
Section titled “Important Notes”-
Global Interpreter Lock (GIL): Python’s GIL restricts only one thread from executing Python bytecode at a time. Therefore, in CPU-intensive tasks, multi-threading may not bring performance improvements. For I/O-intensive tasks, multi-threading is still beneficial.
-
Thread Safety: In a multi-threaded environment, ensure that access to shared resources is thread-safe to avoid data races and deadlocks.
-
Thread Count: Creating too many threads may exhaust system resources and affect program performance. Control the number of threads reasonably, or use a thread pool (
ThreadPoolExecutor) to manage threads.