This article is participating in Python Theme Month. See the link to the event for more details

In this Python multithreading tutorial, you’ll see different ways to create threads and learn how to synchronize thread-safe operations. Each section of this article contains an example and sample code to step by step explain the concept.

Multithreading, by the way, is a central concept in software programming supported by almost all high-level programming languages. So the first thing you should know is what threads are and what multithreading means in computer science.

What are threads in computer science?

In software programming, a thread is the smallest unit of execution with a separate set of instructions. It is part of a process and runs in the same context that shares the program’s runnable resources, such as memory. A thread has a starting point, an execution order, and a result. It has an instruction pointer that holds the current state of the thread and controls what order to execute next.

What is multithreading in computer science?

The ability of a process to execute multiple threads in parallel is called multithreading. Ideally, multithreading can significantly improve the performance of any program. Also, Python’s multi-threading mechanism is user-friendly and you can learn it quickly.

Advantages of multithreading

  • Multithreading can significantly increase computing speed on multiprocessor or multi-core systems because each processor or core simultaneously processes a separate thread.
  • Multithreading allows a program to remain responsive while one thread waits for input while another thread runs the GUI. This statement applies to multiprocessor or uniprocessor systems.
  • All 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. Threads can also have local variables of their own.

Disadvantages of multithreading

  • On a uniprocessor system, multithreading does not affect computing speed. Performance can suffer due to the overhead of managing threads.
  • Access to shared resources must be synchronized to prevent mutual exclusion. It directly results in more memory and CPU utilization.
  • Multithreading increases the complexity of a program, which makes debugging difficult.
  • It increases the possibility of potential deadlocks.
  • When a thread cannot access a shared resource on a regular basis, it can cause starvation. The application will not be able to resume its work.

So far, you’ve read about the theoretical concepts of threading. If you are not familiar with Python, we recommend that you read our 30 quick Python coding tips that can also help you write Python multithreaded code. Many of our readers have used these techniques and have been able to improve their coding skills.

Python multithreaded module

Python provides two modules for implementing threads in programs.

  • 支那And * * module
  • 支那< > thread* * module.

Note: For your information, Python 2.x used to have the < Thread > module. However, it was deprecated in Python 3.x and renamed the < _thread> module for backward compatibility.

The main difference between the two modules is that the <_ thread > module implements threads as functions. The < threading > module, on the other hand, provides an object-oriented way to enable thread creation.

How do I create a thread using the thread module?

If you decide to use the < thread > module in your program, use the following method to generate threads.

# grammar

thread.start_new_thread ( function, args[, kwargs] )
Copy the code

This approach is very efficient and straightforward for creating threads. You can use it to run programs in Linux and Windows.

This method starts a new thread and returns its identifier. It calls the function specified as a “function” argument with the passed argument list. When < function > returns, the thread exits silently.

Here, args is a parameter tuple; Calling < function > with an empty tuple takes no arguments. The optional < kwargs > argument specifies a dictionary for keyword arguments.

** If < function > terminates due to an unhandled exception, a stack trace is printed and the thread exits (it does not affect the other threads, which continue to run). Use the following code to learn more about threads.

Basic Python multithreading example

Python multithreading example.
#1. Calculate factorials recursively.
#2. Use threads to call factorial functions.

from _thread import start_new_thread
from time import sleep

threadId = 1 # Thread counter
waiting = 2 #2 Seconds of waiting time

def factorial(n) :
    global threadId
    rc = 0
    
    if n < 1:   # base case
        print("{}: {}".format('\nThread', threadId ))
        threadId += 1
        rc = 1
    else:
        returnNumber = n * factorial( n - 1 )  # recursive call
        print("{} != {}".format(str(n), str(returnNumber)))
        rc = returnNumber
    
    return rc

start_new_thread(factorial, (5, ))
start_new_thread(factorial, (4)),print("Waiting for threads to return...")
sleep(waiting)
Copy the code

You can run the above code in your local Python terminal, or you can use any online Python terminal. When this program is executed, it produces the following output.

Program output

Python multithreading: Program output -Wait for the thread to return... Thread:1
1! =1
2! =2
3! =6
4! =24
5! =120

Thread: 2
1! =1
2! =2
3! =6
4! =24
Copy the code

How do I create a thread using the thread module?

The latest < threading > module provides rich features and better threading support than the legacy < thread > module discussed in the previous section. The < threading > module is a good example of Python multi-threading.

The < threading > module combines all the methods of the < Thread > module and exposes some additional methods

  • Threading.activecount () : It finds the total. Active thread object.
  • Threading.currentthread () : You can use this to determine the number of thread objects in the caller’s thread control.
  • Threading.enumerate () : This will give you a complete list of currently active thread objects.

In addition to the above methods, the < threading > module also provides the < Thread > class, where you can try to implement threads. It is an object-oriented variant of Python multi-threading.

The < Thread > class publishes the following methods.

Class method Method statement
run(): It is an entry point function for any thread.
start(): The start() method fires a thread when the run method is called.
join([time]): The join() method enables the program to wait for the thread to terminate.
isAlive(): The isAlive() method validates the active thread.
getName(): The getName() method retrieves the name of the thread.
setName(): The setName() method updates the name of the thread.

Use the thread module to implement the steps of the thread

You can implement a new thread using the < threading > module by following these steps.

  • From the <Thread> class constructs a subclass.
  • Cover <init(self [,args])> method to provide parameters on request.
  • Next, override <run(self [,args])> method to write the thread’s business logic.

Once a new < Thread> subclass is defined, it must be instantiated to start a new Thread. Then, the < start()> method is called to start it. It eventually calls the < run()> method to execute the business logic.

Example – Create a thread class to print dates

Print the current date.
#1. Use the threading.Thread class to define subclasses.
#2. Instantiate the subclass and fire 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("\nStarting " + 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("[] {} {}, {}".format( threadName, counter, datefields[0]))# Create new thread
thread1 = myThread("Thread".1)
thread2 = myThread("Thread".2)

# Start new thread
thread1.start()
thread2.start()

thread1.join()
thread2.join()
print("\nExiting the Program!!!")
Copy the code

Program output

Starting Thread
Thread[1] :2021- 07 -22
Exiting Thread

Starting Thread
Thread[2] :2021- 07 -22
Exiting Thread

Exiting the Program!!!
Copy the code

Python Multithreading — Synchronous threads

The < Threading > module has built-in functionality that implements locking, allowing you to synchronize threads. Locking is needed to control access to shared resources to prevent data corruption or loss.

You can apply the Lock by calling the Lock() method, which returns the new Lock object. You can then force threads to run synchronously by calling the fetch (block) method on the lock object.

The optional blocking parameter specifies whether the thread is waiting to acquire the lock.

  • Case Blocking= 0: The thread returns zero immediately if the lock fails to be acquired, and one on success.
  • Case Blocking= 1: The thread blocks and waits for the lock to be released.

The release() method of a lock object is used to release the lock when it is no longer needed.

Fys, Python’s built-in data structures (e.g., lists, dictionaries) are thread-safe because they have the side-effect of the atomic bytecode used to manipulate them. Other data structures or basic types implemented in Python, such as integers and floating point numbers, do not have this protection. To prevent simultaneous access to one object, we use a Lock object.

Locking multithreading example

#Python multithreaded example to demonstrate locking.
#1. Use the threading.Thread class to define subclasses.
#2. Instantiate the subclass and fire the thread.
#3. Implement the lock in the 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("\nStarting " + self.name)
        # Acquire lock synchronization thread
        threadLock.acquire()
        print_date(self.name, self.counter)
        Release the 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("[] {} {}, {}".format( threadName, counter, datefields[0] ))

threadLock = threading.Lock()
threads = []

# Create new thread
thread1 = myThread("Thread".1)
thread2 = myThread("Thread".2)

# Start new thread
thread1.start()
thread2.start()

# Add thread to thread list
threads.append(thread1)
threads.append(thread2)

Wait for all threads to complete
for thread in threads:
    thread.join()

print("\nExiting the Program!!!")
Copy the code

Program output

Starting Thread
Thread[1] :2021- 07 -22
Exiting Thread

Starting Thread
Thread[2] :2021- 07 -22
Exiting Thread

Exiting the Program!!!
Copy the code

Summary – Python multithreading for beginners

I hope you found this Python multithreading tutorial very interesting and engaging. If you enjoyed this article and are interested in seeing more of it, follow me here (Github/Gitee) for more information. Here is a summary of all my original and work source code

More on this at 🧵

  • Python Socket programming essentials | Python theme month
  • 30 Python tutorials and tips | Python theme month
  • Python statements, expressions, and indentation | Python theme month
  • Python keywords, identifiers, and variables | Python theme month
  • How to write comments and multi-line comments in Python | Python Theme Month
  • 20 Python Tips Everyone must Know | Python Theme month
  • Python data types — Basic to advanced learning | Python topic month
  • 100 Basic Python Interview Questions Part 1 (1-20) | Python topic month
  • 100 Basic Python Interview Questions Part 2 (21-40) | Python topic month
  • 100 Basic Python Interview Questions Part 3 (41-60) | Python topic month
  • 100 Basic Python Interview Questions Part 4 (61-80) | Python topic month
  • 100 Basic Python Interview Questions Part 5 (81-100) | Python topic month

Recommended articles of the past:

  • Teach you to use Java to make a gobang game
  • Interesting way to talk about the history of JavaScript ⌛
  • The output of a Java program | Java exercises 】 【 7 sets (including parsing)
  • ❤️5 VS Code extensions that make refactoring easy ❤️
  • It is said that if you have light in your eyes, everywhere you go is light
  • 140000 | 400 multichannel JavaScript 🎓 interview questions with answers 🌠 items (the fifth part 371-424)

If you do learn something new from this post, like it, bookmark it and share it with your friends. 🤗 Finally, don’t forget ❤ or 📑 for support