February 16, 2021

Python Multi-threading Tutorial

In this tutorial we’ll see the support for multi-threading in Python.

What is multi-tasking

In concurrent programming there are two types of multitasking-

  1. Process based multitasking
  2. Thread based multitasking

Process based multitasking

We run a lot of processes simultaneously on our computer for example working on a word document while playing songs and also having some sites opened in a browser. This is an example of running separate processes concurrently. Here just to clarify it, with a single processor only a single process is executed by a processor at any given time. Processor divides its execution time between different processes and executes them for the given time slice, that’s why term "time slicing" is also used.

For example if there are three processes loaded into memory and all of them have to be executed then processor may divide 1 millisecond into the slices of 1/3 millisecond each and execute them in parallel, though the context switching between processes happen so fast that as a user we get a feel that all the processes are running simultaneously or concurrently.

Process based multitasking

A process has a self-contained execution environment. A process has its own run-time resources like memory space so processes are considered heavyweight tasks.

Thread based multitasking

With in a same program you can have several tasks running like in a song player you can start playing a song and at the same time you can add more songs to your playlist. With in a program you can spawn separate threads to execute separate tasks. This concept of dividing a program into separate sub-tasks and using separate threads to execute these sub-tasks to make overall execution faster and your program more responsive is known as multi-threading.

Thread based multitasking

Threads are considered lightweight processes that are spawned with in a process and share its memory and processor time.

Multi-threading in Python

Python has in-built support for multi-threading programming in the form of threading module. The threading module has a Thread class which encapsulates thread functionality.

You can create a Thread object using one of the following ways-

  1. By creating Thread instance and passing the function that has to be executed as one of the argument to the constructor of the Thread.
  2. By creating a class that extends Thread class and overrides run method.

Once a thread object is created, its activity must be started by calling the thread’s start() method. This invokes the run() method in a separate thread of control.

Python thread creation example

1. In the following example we’ll call threading.Thread() to create Thread instance. We’ll create two Thread instances to show how you can pass arguments (passing argument is optional) to the target function.

import threading

def print_thread_info():
    print('Thread Name: ' + threading.current_thread().name)


def print_message(msg):
    print('From Thread: ' + threading.current_thread().name + ' Message is- ' + msg)


if __name__ == "__main__":
    # Creating threads
    t1 = threading.Thread(target=print_thread_info)
    t2 = threading.Thread(target=print_message, name='MyThread', args=('Hello I am a thread',))
    # starting threads
    t1.start()
    t2.start()
Output
Thread Name: Thread-1
From Thread: MyThread Message is- Hello I am a thread

In the program points to note are-

    • Since you are using multi-threading so threading module has to be imported.
      import threading
      
    • Thread instances are created using threading.Thread() constructor. In the first instance only target function (function to be executed by thread) is passed. In the second instance apart from target function, thread name and arguments to the target function are also passed.
    • To start thread’s activity start() method has to be invoked on a thread.

2. In the following example we’ll subclass Thread class and override run() method.

import threading

class MyThread(threading.Thread):
  def run(self):
    print('In run method Thread Name: ' + threading.current_thread().name)

# Creating thread
t1 = MyThread()
# starting thread
t1.start()
Output
In run method Thread Name: Thread-1

In the program points to note are-

  • Thread class is extended by the class so MyThread class is also of type Thread.
  • run() method is overridden and that is where you write the logic that has to be executed by a thread.
  • To start thread’s activity start() method has to be invoked on a thread which arranges for the object’s run() method to be invoked in a separate thread of control. The start() method must be called at most once per thread object.

Python Thread class methods

Some of the important methods and properties available in the Thread class are as following.

Method Description
start() Start the thread. This method must be called at most once per thread object. Once the thread is started it arranges for the object’s run() method to be invoked in a separate thread of control.
run() This method has the code that is executed by a thread. You may override this method in a subclass. If thread instance is created using threading.Thread() constructor then run() method invokes the callable object passed to the object’s constructor as the target argument.
join(timeout) This method blocks the calling thread until the thread whose join() method is called terminates
name Property that represents thread name.
setName(name) Method for setting thread name
getName() Method for getting thread name. It is recommended to use name property directly instead of these getter/setter methods.
is_alive() Returns True if the thread is alive False otherwise
daemon A boolean value indicating whether this thread is a daemon thread (True) or not (False).
isDaemon() Method for getting if the thread is a daemon thread or not. Returns True if it is False otherwise.
setDaemon(flag) Setting a thread as a daemon thread by passing True. It is recommended to use daemon property directly rather than these getter/setter methods.

Main thread in Python

When you write a Python program, Python Virtual Machine (PVM) starts a new thread to execute the statements in your program. Which means whenever any Python program is executing one thread is always started that thread is known as main thread in Python. Following example prints the name of currently executing thread.

import threading

def print_info():
    print('Thread Name: ' + threading.current_thread().name)

print_info()
Output
Thread Name: MainThread

As you can see in the program no thread is created explicitly still MainThread is started.

There is also a threading.main_thread() method (available Python 3.4 onward) which returns the main thread object.

import threading

def print_info():
    #print('Thread Name: ' + threading.current_thread().name)
    if threading.current_thread() is threading.main_thread():
        print('Current thread is main thread')

print_info()
Output
Current thread is main thread

That's all for the topic Python Multi-threading Tutorial. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment