Python Multithreading – Complete Guide

Python Multithreading

A Thread is a lightweight subprocess used to execute tasks in parallel. Python supports multithreading, allowing multiple tasks to run simultaneously within the same program.

Operating Systems use multithreading to run multiple applications at the same time. Game development, animations, and real-time systems require multithreading to run parallel executions smoothly.

Thread Life Cycle

Thread Life Cycle

Basic Syntax of Threading

import threading

class Classname(threading.Thread):
    # functionality
    pass

Example: Simple Thread Execution

import threading
import time

class ThreadExample(threading.Thread):
    def run(self):
        for i in range(1, 10):
            print("Process is " + str(i))
            time.sleep(1)

t1 = ThreadExample()  # New state, thread memory allocated
t1.start()            # Moves thread to running state

Multithreading Example

import threading
import time

class ThreadExample(threading.Thread):
    def run(self):
        for i in range(1,10):
            print("Process is " + str(i))
            time.sleep(1)

t1 = ThreadExample()
t1.start()

t2 = ThreadExample()
t2.start()

t3 = ThreadExample()
t3.start()

Thread Synchronization using join()

Thread synchronization ensures that one thread waits until another completes.

import threading
import time

class ThreadExample(threading.Thread):
    def run(self):
        for i in range(1, 10):
            print("Process is " + str(i))
            time.sleep(1)

t1 = ThreadExample()
t1.start()
t1.join()

t2 = ThreadExample()
t2.start()
t2.join()

t3 = ThreadExample()
t3.start()

Example: Thread with Inheritance

import threading
import time

class Thread1(threading.Thread):
    def __init__(self):
        super(Thread1, self).__init__()
        self.num = int(input("Enter number: "))

    def run(self):
        for i in range(1, 11):
            print(self.num * i)
            time.sleep(1)

class Thread2(Thread1):
    def __init__(self):
        super(Thread2, self).__init__()

    def run(self):
        self.s = ''
        self.fact = 1
        for i in range(self.num, 0, -1):
            self.s += str(i) + "*"
            self.fact *= i
            time.sleep(1)
        print("result is " + self.s + " = " + str(self.fact))

t1 = Thread1()
t1.start()
t1.join()

t2 = Thread2()
t2.start()

Threading in Procedural Programming (Using target)

import threading
import time

def fun():
    for i in range(1, 10):
        print(i)
        time.sleep(1)

t1 = threading.Thread(target=fun)
t1.start()
t1.join()

t2 = threading.Thread(target=fun)
t2.start()

Class-Based Thread Example (Table Program)

import threading
import time

class Table(threading.Thread):
    def __init__(self, num):
        super().__init__()
        self.num = num

    def run(self):
        for i in range(1, 11):
            print(self.num * i)
            time.sleep(1)

t = Table(5)
t.start()
t.join()

t1 = Table(9)
t1.start()

Method-Based Thread Example (Table Program)

import threading
import time

def table(num):
    for i in range(1, 11):
        print(num * i)
        time.sleep(1)

t = threading.Thread(target=lambda: table(5))
t.start()

t1 = threading.Thread(target=lambda: table(9))
t1.start()

Thread Synchronization Using Lock()

When multiple threads use the same resource (file, variable), use Lock to avoid data corruption.

Lock Example

import threading
import time
from random import randint

class SharedCounter(object):
    def __init__(self, val=0):
        self.lock = threading.Lock()
        self.counter = val

    def increment(self):
        print("Waiting...")
        self.lock.acquire()
        try:
            print("Acquired", self.counter)
            self.counter += 1
        finally:
            print("Released lock, counter value:", self.counter)
            self.lock.release()

def xyz(c):
    r = randint(1, 5)
    for i in range(r):
        c.increment()
    print("Done")

sCounter = SharedCounter()

t1 = threading.Thread(target=xyz, args=(sCounter,))
t1.start()

t2 = threading.Thread(target=xyz, args=(sCounter,))
t2.start()

print("Counter:", sCounter.counter)

Thread Assignments

  1. Create a Dice Game using multithreading
  2. Create an Automated ATM System with multithreaded operations