Multithreading is a core concept of software programming that almost all the high-level programming languages support. And Python multithreading is one of the best examples of simplistic implementation of threads.
In software programming, a thread is the smallest unit of execution with the independent set of instructions. It is a part of the process and operates in the same context sharing program’s runnable resources like memory. A thread has a starting point, an execution sequence, and a result. It has an instruction pointer that holds the current state of the thread and controls what executes next in what order.
Similarly, the ability of a process to execute multiple threads parallelly is called multithreading. Ideally, multithreading can significantly improve the performance of any program. And Python multithreading mechanism is pretty user-friendly which you can learn quickly.
In this Python multithreading tutorial, we’ll teach different methods to create threads and implement synchronization. Let’s first have a look into some of the major pros and cons of multithreading.
Python Multithreading – Pros:
- Multithreading can significantly improve the speed of computation on multiprocessor or multi-core systems because each processor or core handles a separate thread concurrently.
- Multithreading allows a program to remain responsive while one thread waits for input and another runs a GUI at the same time. This statement holds true for both multiprocessor or single processor systems.
- All the threads of a process have access to its global variables. If a global variable changes in one thread, it is visible to other threads as well. A thread can also have its own local variables.
Python Multithreading – Cons:
- On a single processor system, multithreading wouldn’t impact the speed of computation. In fact, the system’s performance may downgrade due to the overhead of managing threads.
- Synchronization is required to avoid mutual exclusion while accessing shared resources of the process. It directly leads to more memory and CPU utilization.
- Multithreading increases the complexity of the program thus also making it difficult to debug.
- It raises the possibility of potential deadlocks.
- It may cause starvation when a thread doesn’t get regular access to shared resources. It would then fail to resume its work.
Well so far, you’ve read the theoretical concepts about threads. If you are new to Python, we would suggest you go through our 10 quick Python coding tips that can help you in writing Python multithreading code as well. Many of our readers have used these tips and were able to improve their coding skills.
Python Multithreading Modules for Thread Implementation.
Python offers two modules to implement threads in programs.
- <thread> module and
- <threading> module.
For your information, <thread> module is deprecated in Python 3 and renamed to <_thread> module for backward compatibility. But we’ll explain both methods because many of the users still use legacy Python versions.
The key difference between the two modules is that the module <thread> implements a thread as a function. On the other hand, the module <threading> offers an object-oriented approach to enable thread creation.
1- How to use the thread module to create threads.
If you decide the <thread> module to apply in your program, then use the following method to spawn threads.
thread.start_new_thread ( function, args[, kwargs] )
This method is quite simple and efficient way to create threads. You can use it to run programs in both Linux and Windows.
This method starts a new thread and returns its identifier. It’ll invoke the function specified as the “function” parameter with the passed list of arguments. When the <function> returns, the thread would silently exit.
Here, args is a tuple of arguments; use an empty tuple to call <function> without any arguments. The optional <kwargs> argument specifies the dictionary of keyword arguments.
If the <function> terminates with an unhandled exception, a stack trace is printed and then the thread exits (It doesn’t affect other threads, they continue to run). Use the below code to learn more about threading.
Basic Python multithreading example.
#Python multithreading example. #1. Calculate factorial using recursion. #2. Call factorial function using thread. from thread import start_new_thread threadId = 1 def factorial(n): global threadId if n < 1: # base case print "%s: %d" % ("Thread", threadId ) threadId += 1 return 1 else: returnNumber = n * factorial( n - 1 ) # recursive call print(str(n) + '! = ' + str(returnNumber)) return returnNumber start_new_thread(factorial,(5, )) start_new_thread(factorial,(4, )) c = raw_input("Waiting for threads to return...\n")
You can run the above code in your local Python terminal or use any online Python terminal. Once you execute this program, it’ll produce the following output.
# Python multithreading: program output- Waiting for threads to return... Thread: 1 1! = 1 2! = 2 3! = 6 4! = 24 Thread: 2 1! = 1 2! = 2 3! = 6 4! = 24 5! = 120
You can quickly find and choose the online Python terminal from the below article on our blog. Here, we’ve compiled a list of 7 best online Python terminals to test and run your code on the fly. We’ve tested all the Python multithreading examples source code with these online terminals as well.
2- How to use the threading module to create threads.
The latest <threading> module provides rich features and greater support for threads than the legacy <thread> module discussed in the previous section. The <threading> module is an excellent example of Python Multithreading.
The <threading> module combines all the methods of the <thread> module and exposes few additional methods.
- threading.activeCount(): It finds the total no. of active thread objects.
- threading.currentThread(): You can use it to determine the number of thread objects in the caller’s thread control.
- threading.enumerate(): It will give you a complete list of thread objects that are currently active.
Apart from the above methods, <threading> module also presents the <Thread> class that you can try for implementing threads. It is an object-oriented variant of Python multithreading.
The <Thread> class publishes the following methods.
|Class Methods||Method Description|
|run():||It is the entry point function for any thread.|
|start():||The start() method triggers a thread when run method is called.|
|join([time]):||The join() method enables a program to wait for threads to terminate.|
|isAlive():||The isAlive() method verifies an active thread.|
|getName():||The getName() method retrieves the name of a thread.|
|setName():||The setName() method updates the name of a thread.|
If you wish, you can refer the native Python docs to dig deeper into the <threading> module functionality.
2.1- Steps to implement threads using the threading module.
You may follow the below steps to implement a new thread using the <threading> module.
- Construct a subclass from the <Thread> class.
- Override the <__init__(self [,args])> method to supply arguments as per requirements.
- Next, override the <run(self [,args])> method to code the business logic of the thread.
Once you define the new <Thread> subclass, you have to instantiate it to start a new thread. Then, invoke the <start()> method to initiate it. It will eventually call the <run()> method to execute the business logic.
Example – Create a thread class and object to print current date.
#Python multithreading example to print current date. #1. Define a subclass using Thread class. #2. Instantiate the subclass and trigger the thread. import threading import datetime class myThread (threading.Thread): def __init__(self, name, counter): threading.Thread.__init__(self) self.threadID = counter self.name = name self.counter = counter def run(self): print "Starting " + self.name print_date(self.name, self.counter) print "Exiting " + self.name def print_date(threadName, counter): datefields =  today = datetime.date.today() datefields.append(today) print "%s[%d]: %s" % ( threadName, counter, datefields ) # Create new threads thread1 = myThread("Thread", 1) thread2 = myThread("Thread", 2) # Start new Threads thread1.start() thread2.start() thread1.join() thread2.join() print "Exiting the Program!!!"
2.2- Python Multithreading – Synchronizing threads.
The <threading> module has built in functionality to implement locking that allows you to synchronize threads. Locking is required to control access to shared resources to prevent corruption or missed data.
You can call Lock() method to apply locks, it returns the new lock object. Then, you can invoke the acquire(blocking) method of the lock object to enforce threads to run synchronously.
The optional blocking parameter specifies whether the thread waits to acquire the lock.
- In case, blocking is set to zero, the thread returns immediately with a zero value if the lock can’t be acquired and with a 1 if the lock was acquired.
- In case, blocking is set to 1, the thread blocks and wait for the lock to be released.
The release() method of the lock object is used to release the lock when it is no longer required.
Just for your information, Python’s built-in data structures such as lists, dictionaries are thread-safe as a side-effect of having atomic byte-codes for manipulating them. Other data structures implemented in Python or basic types like integers and floats, don’t have that protection. To guard against simultaneous access to an object, we use a Lock object.
Python multithreading example for locking.
#Python multithreading example to demonstrate locking. #1. Define a subclass using Thread class. #2. Instantiate the subclass and trigger the thread. #3. Implement locks in thread's run method. import threading import datetime exitFlag = 0 class myThread (threading.Thread): def __init__(self, name, counter): threading.Thread.__init__(self) self.threadID = counter self.name = name self.counter = counter def run(self): print "Starting " + self.name # Acquire lock to synchronize thread threadLock.acquire() print_date(self.name, self.counter) # Release lock for the next thread threadLock.release() print "Exiting " + self.name def print_date(threadName, counter): datefields =  today = datetime.date.today() datefields.append(today) print "%s[%d]: %s" % ( threadName, counter, datefields ) threadLock = threading.Lock() threads =  # Create new threads thread1 = myThread("Thread", 1) thread2 = myThread("Thread", 2) # Start new Threads thread1.start() thread2.start() # Add threads to thread list threads.append(thread1) threads.append(thread2) # Wait for all threads to complete for t in threads: t.join() print "Exiting the Program!!!"
Summary – Python Multithreading Guide for Beginners.
We wish that you would find this Python Multithreading tutorial very interesting and intuitive. Moreover, we’ve added few illustrations in this tutorial that would surely help you to uplift your Python skills.
We also recommend that you should practice with new multithreading assignments for better results that will boost your Python programming skills and knowledge.
We request you to distribute this post among your friend circle and on the social media platforms you like.
Keep learning & Happy Sharing!!!