Python Multithreading
In python, we can implement multithreading. In this tutorial, we will understand the basics of implementing multithreading in a python programming language. Multithreading is just like multiprocessing. We use it to perform multi-tasking. Before we understand more about multithreading, first, let’s understand threading.
What is a thread?
Thread can be explained as the execution of the smallest sequence of instructions that can be executed independently by a scheduler of an operating system. It is the basic unit of CPU utilisation. A process can be defined as a program that is being executed, and all processes have three main components, which are:
- A program that will be executed.
- The data needed for that program, like variables, workspace, buffers, etc.
- The state of the process.
Now, a thread is the smallest unit of processing that will get executed in an operating system. It is an entity in the process which is scheduled for execution. It is a sequence of those instructions in the code that can be executed independently in any other program. It contains all the information in a Thread Control Block (TCB).
These are the information that gets stored in a TCB:
- Parent Process Pointer: It contains a pointer pointing to the Process Control Block (PCB) where the threads live on.
- Thread ID: It is the unique id assigned to all the new threads.
- Thread State: It is the state of the thread, which can be running, ready, starting, waiting and done.
- Program counter: It is a register which stores the address of the instruction being executed.
- Register Set: It is the register assigned to the thread for computation.
- Stack Pointer: It is the pointer pointing to the stack which stores the local variables.
What is Multithreading?
Multithreading enables the CPU to execute different threads concurrently inside a process. In multithreading, we share the data with the main thread and, therefore, can easily communicate or share information with each other. Threads are very light-weighted processes which means they don’t need a lot of memory. In multi-thread, all the threads have their own register set and local variables (stored in a stack), but they all share global variables and the program code.
Multithreading can be achieved by switching between threads. This process of switching is known as Context Switching. In this, the state of one thread is saved while the other is executed or loaded.
Starting a thread in python
thread.start_new_thread ( function, args[, kwargs] )
This method is used to create very fast and efficient threads. Here, args is the argument or a tuple of argument while kwargs is a keyword argument.
In python, we use the threading module for creating and spawning multiple threads in a program.
Let’s understand with a very simple example.
Example:
import threading
def triple(num):
# function to print triple of given num
print("Triple: {}".format(3 * num))
def double(num):
# function to print double of given num
print("Double: {}".format(2 * num))
if __name__ == "__main__":
# creating thread
th1 = threading.Thread(target=double, args=(10,))
th2 = threading.Thread(target=triple, args=(10,))
# starting thread 1
th1.start()
# starting thread 2
th2.start()
# wait until thread 1 is completely executed
th1.join()
# wait until thread 2 is completely executed
th2.join()
# both threads completely executed
print("Done!")
Output
Double: 20
Triple: 30
Done!
Explanation
In the above line of code, we have imported the threading module using the command import threading. After that, we created two threads with different target functions, which are th1 and th2. After creating the threads, we used the start method to start the thread, which is th1.start and th2.start. In this code, we have used the join method to stop the execution of the main thread until the thread is executed. Because of this, the first thread, th1, will be executed, then th2, and then we will come out of the program.
Threading Module
A threading module in python gives very powerful and high-level support for the threads in the program. It gives some additional modules like-
- threading.activeCount() : it returns the total number of active threads.
- threading.currentThread(): It returns the total number of threads in the caller control.
- threading.enumerated(): It returns a list of threads that are active presently.
Some additional methods that a threading module has are:
- run(): It is the entry point of the thread.
- start(): It starts a thread after calling the run method.
- join([time]): It waits for a thread to terminate.
- isAlive(): It checks if a method is still executing or not.
- getName(): It returns the name of the thread.
- setName(): It sets the name of the thread.