Python Multithreading Tutorial - Concurrent Programming

Elliot Forbes Elliot Forbes ⏰ 3 Minutes 📅 Apr 15, 2017

In this tutorial, we are going to be looking at how you you can use multithreading within your Python applications.

What is Multithreading?

Modern computers tend to feature a CPU that has multiple processing cores, each of these cores can run many threads simultaneously which gives us the ability to perform several tasks concurrently. This tutorial will hopefully show you how to get started with Python’s threading module.

Objectives:

  1. Creating and Running Threads
  2. Teaching the Limitations of Python’s threading implementation

Creating Threads in Python

To begin with we are going to want to create a new file and call it worker.py, this will contain all our code for one of our threads. To begin with we are going to create a class in python and have it import and extend the threading module.

import threading

class Worker(threading.Thread):
    ## Our workers constructor, note the super() method which is vital if we want this
    ## to function properly
    def __init__(self):
        super(Worker, self).__init__()

    def run(self):
        for i in range(10):
           print(i)

Now that we have our worker class we can start work on our main class. Create a new python file and call it main.py and put the following code in:

import threading
from worker import Worker

def main():
    ## This initializes ''thread1'' as an instance of our Worker Thread
   thread1 = Worker()
    ## This is the code needed to run our newly created thread
    thread1.start()

  if __name__ == "__main__":
      main()

That''s all the code you need to successfully create and instantiate a thread in python. If you can run python through your command line then open up a new terminal at your current folder and type ''python main.py''. You should hopefully see the output of the above program should no errors occur.

Exercise:

Try instantiating more threads by creating new Worker() objects and then start them:

    thread1 = Worker(1)
    thread2 = Worker(2)
    thread3 = Worker(3)
    thread1.start()
    thread2.start()
    thread3.start()

When you run this you should see output that looks something like this:  Notice that the outputted numbers are out of order, this basically shows you the precise order in which the threads have completed their tasks in and shows you the true power of asynchronous programming, multiple threads performing in parallel.

Limitation with Classic Python Threads

One of the main problems with Python’s classic implementation of threads is that they are not truly asynchronous. Performing tests on huge datasets show that the execution times of python threads is not entirely in parallel and you'’ll often find execution times increasing adding multiple threads to programs as often performing these tasks synchronously will greatly reduce execution times. This is due to the way Global Interpreter Lock (GIL) works in Python, this basically ensures that only one line of python code can be compiled at one time.

More about the GIL can be found here: https://wiki.python.org/moin/GlobalInterpreterLock