Python, threading objects
In Python, threading objects are primarily provided by
the threading module, which offers a high-level, object-
oriented API for managing threads.
The core object for creating and managing individual
threads is the Thread class.
1. The Thread Object:
Creation:
A Thread object represents an activity that will be run in a
separate thread of control. You can create
a Thread object in two main ways:
Passing a callable: Provide a target function or a callable
object to the Thread constructor using
the target argument. You can also pass arguments to this
function using the args (for positional arguments)
and kwargs (for keyword arguments) parameters.
Subclassing Thread: Create a new class that inherits
from threading.Thread and override the run() method. This
method will contain the code to be executed by the
thread.
Starting:
Once a Thread object is created, its activity must be
started by calling the start() method. This invokes
the run() method (either the one you provided
as target or the overridden one in a subclass) in a
separate thread of control.
Joining:
The join() method allows a calling thread to wait until the
thread whose join() method is called terminates. This
ensures that the main program or other threads don't
proceed before a specific thread has completed its
execution.
Daemon Threads:
Threads can be marked as "daemon threads." The
significance of this flag is that the entire Python program
exits when only daemon threads are left.
Example of Thread object usage:
import threading
import time
def worker_function(name):
print(f"Thread {name}: Starting")
time.sleep(2) # Simulate some work
print(f"Thread {name}: Finishing")
# Create a Thread object by passing a callable
thread1 = threading.Thread(target=worker_function,
args=("One",))
thread2 = threading.Thread(target=worker_function,
args=("Two",))
# Start the threads
thread1.start()
thread2.start()
# Wait for threads to complete
thread1.join()
thread2.join()
print("Main thread: All threads finished.")
2. Synchronization Objects:
The threading module also provides several
synchronization objects to manage access to shared
resources and coordinate thread execution, including:
Lock:
A basic mutual exclusion lock used to protect critical
sections of code, ensuring only one thread can access a
resource at a time.
RLock (Re-entrant Lock):
Similar to Lock, but allows the same thread to acquire the
lock multiple times, preventing deadlocks in recursive
scenarios.
Condition:
A more advanced synchronization primitive that allows
threads to wait for certain conditions to be met and be
notified when those conditions change.
Semaphore:
A counter-based synchronization object that controls
access to a limited number of resources.
Event:
A simple flag that can be set or cleared to signal events
between threads. Threads can wait for an event to be set
using wait().
Barrier:
Forces a specified number of threads to wait at a
common point until all of them have arrived before
allowing them to proceed.
Threading Objects in python
Python's threading module provides high-level threading
objects to create, manage, and synchronize multiple
threads of execution within a single process.
These objects are crucial for building concurrent
applications, especially those that are I/O-bound (e.g.,
network requests, file operations), as they improve
responsiveness and resource utilization.
Key threading objects include:
1. Thread Object
The Thread class is the primary way to represent and control
an activity running in a separate thread.
Creation: You can create a Thread object in two main ways:
o Passing a callable: Specify a target function and its arguments
to the constructor.
o Subclassing Thread : Override the run() method in a subclass
to define the thread's activity.
Key methods and attributes:
o start() : Starts the thread's activity. Internally calls
the run() method.
o run() : The entry point for the thread's activity. This method is
executed when start() is called.
o join([timeout]) : Blocks the calling thread (e.g., the main thread)
until the thread whose join() method is called terminates. An
optional timeout can be specified.
o is_alive() : Returns True if the thread is still
running, False otherwise.
o daemon : A boolean flag; if set to True , the entire Python
program exits when only daemon threads are left.
Example:
import threading
import time
def task(name, delay):
print(f"Thread {name}: starting task")
time.sleep(delay)
print(f"Thread {name}: finishing task")
# Create thread objects
t1 = threading.Thread(target=task, args=("T1", 2))
t2 = threading.Thread(target=task, args=("T2", 1))
# Start the threads
t1.start()
t2.start()
# Wait for both threads to complete
t1.join()
t2.join()
print("Main thread: all tasks finished")
2. Synchronization Objects
When multiple threads access shared resources,
synchronization objects are vital to prevent race conditions
and ensure thread safety.
Lock : The simplest synchronization primitive. It's in one of two
states: "locked" or "unlocked". Only one thread can acquire
the lock at a time, forcing other threads to wait until it is
released. It can be used with the with statement to ensure
automatic release.
lock = threading.Lock()
with lock:
# Critical section: only one thread can access this block at a time
shared_resource += 1
RLock (Reentrant Lock): Allows a single thread to acquire the
same lock multiple times without blocking itself, which is
useful in recursive scenarios.
Event : A simple signaling mechanism. An event object manages
an internal flag that can be set to true or cleared to false.
Threads can wait for the flag to become true using
the wait() method.
Semaphore : A counter-based mechanism for controlling access
to a limited number of resources. It allows a specified number
of threads to access a resource concurrently.
Condition : A more advanced synchronization primitive that
allows threads to wait for a specific condition to be met, and
be notified by another thread when the condition changes.
3. Higher-level Abstractions
For simpler task management, the concurrent.futures module
provides the ThreadPoolExecutor , which manages a pool of
threads automatically. The queue module also offers thread-
safe queue classes for communication between threads