Do you think IIT Guwahati certified course can help you in your career?
No
Introduction
Multithreading is a threading technique in Pythonprogramming that allows numerous threads to execute concurrently by fast switching between threads with the assistance of a CPU.
It enables sharing of its data space with the main threads inside a process, which communicate and share information more easily than individual processes. Multithreading aims to carry out numerous processes concurrently, enhancing the application's rendering and performance.
Let’s learn how to achieve Multithreading in Python.
What is a Process?
The program that is dispatched from the ready state and is scheduled in the CPU for execution is called a Process. It can be considered a separate entity with its own memory space, resources, and execution flow. Process Control Board holds the concept of Process. Each process runs in its own address space, which means that it does not share memory with other processes. A process can create other small. These are known as Child Processes. The process is slow as it takes more time to terminate.
The process has the following states.
New: In this state, the process is about to be created.
Ready: Once the process is created it enters the ready state, which means the process is ready to run.
Run: In this state, the process is taken from the ready queue by the CPU and is running.
Blocked or Wait: When the process requests access to I/O and expects input from the user it enters this state.
Terminated or Completed: In this state, the process is killed and PCB is deleted.
Suspend Ready: A process that was initially in the ready state but was moved out of main memory in external storage is in the Suspend Ready state.
Suspend Wait: The process which was performing I/O operation and lack of main memory caused them to move to secondary memory. It is in the Suspend Wait state.
What is a Thread?
A thread is the smallest element of a program or process that runs independently or is scheduled by the operating system. In a computer system, an operating system does multitasking by partitioning the process into threads. A thread is a faster process that ensures each process is run independently on the system.
A thread contains information in a Thread Control Block (TCB):-
Thread Identifier: Each new thread receives a unique identifier (TID).
Stack Pointer: Points to the process's thread stack. The thread's local variables are stored in the stack.
Program Counter: It is a register containing the address of the instruction currently being executed by the thread.
Thread State: It can be running, ready, waiting, start, or done.
Thread Register Set: The registers that have been assigned to the thread for calculations.
Parent Process Pointer: A pointer to the Process Control Block (PCB) of the process that the thread is a part of.
What is Multithreading in Python?
Multithreading is a threading technique that allows numerous threads to execute concurrently by fast switching between threads with the assistance of a CPU. Additionally, it enables sharing of its data space with the main threads inside a process, which communicate and share information more easily than individual processes.
Multiple threads can occur within a single process where:-
Each thread has a unique Register Set and Local Variables (stored in a stack).
All threads inside a process share the Program Code and Global Variables.
Context Switching: In a single-core CPU, the frequent switching between threads is known as Context Switching. In context switching, anytime an interrupt occurs (due to I/O or explicitly set), the state of one thread is stored, and the state of another thread is loaded.
Using multithreading can be a great choice if you want to boost the performance of your application.
Below are some use cases where you can apply Multithreading:
1. Performing I/O bound tasks
Multithreading can give a high performance while performing I/O bound tasks such as reading from or writing to files, network sockets or databases.
2. Parallel Processing
If your application requires heavy computation like if you need to process a large number of images or audio files, you can split the work among multiple threads to speed up the processing time.
3. Asynchronous Programming
Multithreading is frequently used in conjunction with Asynchronous Programming techniques such as callbacks, promises and coroutines. By using multiple threads, you can execute multiple asynchronous operations concurrently, improving the overall performance of your application.
How to Achieve Multithreading in Python?
A thread is basically an independent flow of execution. A single process can consist of multiple threads. Multithreading in Python involves creating and managing multiple threads within a program. Threads execute concurrently, enabling parallel execution of tasks. This can improve performance, facilitate concurrent operations, and enhance responsiveness, especially for I/O-bound tasks or operations involving waiting.
To achieve multithreading in Python, we can use the following two modules
The Thread Module
The Threading Module
1. The Thread Module
The thread module in Python provides a low-level interface for creating and managing threads. It provides functions like start_new_thread() to create threads and execute target functions. It is widely used for achieving multithreading in Python. However, it lacks some features like synchronization primitives and thread-safe data structures.
In Python 3 the ‘thread’ module is renamed to ‘_thread’.
Implementation of the Thread Module
Following are the steps to implement multithreading using the Thread module.
1. Import the thread module
import _thread
2. Define a target function
Create a function that will be executed by each thread. This function should contain the specific task or computation you want the thread to perform.
# example Target function for the threads
def print_message(message):
for _ in range(5):
print(message)
time.sleep(1)
3. Create a new thread
Call the start_new_thread() function from the thread module, passing the target function as the first argument and any required arguments as subsequent arguments.
# Create two threads
_thread.start_new_thread(print_message, ("Thread 1",))
_thread.start_new_thread(print_message, ("Thread 2",))
4. Keep the main thread alive
To keep the main thread from exiting before the other threads complete their execution, you can add a delay or use a synchronization mechanism like time.sleep() or thread.join().
# Keep the main thread alive
time.sleep(10)
In the following implementation, we defined the print_message() function as the target function for the threads. Each thread will print a message five times with a delay of one second. We create two threads using the start_new_thread() function, passing the target function and the respective message as arguments. Finally, we use time.sleep(10) to keep the main thread alive for 10 seconds.
Output
The thread module is considered low-level, and the threading module provides a higher-level and more convenient interface for working with threads in Python.
2. The Threading Module
The `threading` module in Python provides a high-level interface for creating and managing threads. It includes the `Thread` class to create threads, synchronization primitives like locks and semaphores, and thread-safe data structures. The `threading` module allows concurrent execution of tasks, facilitates coordination between threads, and offers a more convenient and powerful approach to multithreading compared to the lower-level `thread` module.
Implementation of the Threading Module
Following are the steps to implement multithreading using the Threading module.
1. Import the threading module:
import threading
2. Define a target function
Create a function that will be executed by each thread. This function should contain the specific task or computation you want the thread to perform. We will use the print_message(message) function as our example target function.
# Example target function
def print_message(message):
for _ in range(5):
print(message)
time.sleep(1)
3. Instantiate a Thread object
Create two instances of the Thread class, passing the target function as an argument.
Call the start() method on the Thread object to initiate the execution of the target function in a separate thread.
# Start the threads
thread1.start()
thread2.start()
5. Wait for thread completion
If you want to wait for the thread to finish execution before proceeding further, you can call the join() method on the thread object. This will block the program's execution until the thread completes.
# Wait for threads to finish
thread1.join()
thread2.join()
print("All threads have completed.")
In Python, a multithreaded priority queue is a data structure that allows multiple threads to access and manipulate a collection of items with priorities. Items in the queue are processed based on their priorities, and threads can add or remove items while maintaining the order defined by their priorities.
The queue.PriorityQueue class in Python's queue module provides a thread-safe priority queue implementation that can be used in a multithreaded environment.
Advantages of Multithreading in Python (Make it H2)
The following are the advantages of developing a multithreaded application in Python:-
It guarantees efficient use of computer system resources
Multithreaded apps are more responsive
It is more economical since it distributes resources and its state with child threads
Due to similarity, it increases the efficiency of the multiprocessor architecture
It saves time by running numerous threads concurrently
The system does not need a lot of memory to store several threads
Frequently Asked Questions
Why multithreading is important in Python?
Multithreading is a powerful tool in Python that allows you to run multiple threads concurrently in a single program. This can greatly improve the performance of your application, as it allows you to perform multiple tasks simultaneously.
What is multithreading and multitasking in Python?
In multitasking, the CPU is provided in order to execute many tasks at a time. While in multithreading also, a CPU is provided in order to execute many threads from a process at a time. 6. In multitasking, processes don't share the same resources, each process is allocated separate resources.
Is Python multithreading or multiprocessing?
Python supports both multithreading and multiprocessing. However, Python's multithreading is mainly suitable for I/O-bound tasks due to the Global Interpreter Lock (GIL). Multiprocessing, on the other hand, is used for CPU-bound tasks that require true parallelism by creating separate processes.
Is Python multithreaded or single threaded?
Python is inherently single-threaded because of the Global Interpreter Lock (GIL). While Python supports multithreading using the threading module, it's limited by the GIL, making it more suitable for concurrent I/O-bound tasks. For CPU-bound tasks that require genuine parallelism, Python provides multiprocessing, which uses separate processes to utilize multiple CPU cores.
Conclusion
In this article, we have extensively discussed what a thread is, what multithreading is, and how to achieve multithreading in python with the help of code examples.