Concurrency: Threads vs. Multiprocessing vs. Asyncio

Are your Python programs too slow? Threads, Multiprocessing and Asyncio can be used.
Maybe they are stuck waiting on a file to load, a website to respond, or a CPU-heavy task to finish? Well, my friend, welcome to the world of concurrency!

  • Threads – multiple tasks at once.
  • Multiprocessing  – Splitting the work across multiple CPUs.
  • Asyncio  – Multitasking while waiting.

Here are some examples:

THREADS

Threads are processes that occur when your program is waiting on some other function (like downloads, database queries, or API requests).

  • Example: Running multiple tasks at the same time
    import threading  
    import time  
    
    def print_numbers():
        for i in range(5):
            time.sleep(1)  #delay
            print(f"Number: {i}")
    
    # Creating two threads doing the same thing
    thread1 = threading.Thread(target=print_numbers)
    thread2 = threading.Thread(target=print_numbers)
    
    thread1.start()
    thread2.start()
    
    thread1.join()
    thread2.join()
    print("Done!")

    Instead of waiting for one function to finish before running the next, Python starts both threads together, so they run at the same time.

  • Best for: Tasks that spend time waiting (file input output, API calls)
  • Not good for: CPU-heavy work (parallel execution)

MULTIPROCESSING

Multiprocessing is used when your program is doing heavy calculations (like image processing, number crunching).

  •  Example: Using multiple processors to calculate squares
import multiprocessing  

def square(num):
    return num * num  

if __name__ == "__main__":  
    with multiprocessing.Pool() as pool:  
        results = pool.map(square, range(1, 6))  
        print(results)  # [1, 4, 9, 16, 25]

Each number is sent to a separate processor to be squared at the same time. This makes it much faster.

  • Best for: Complex math, image processing, simulations
  • Not good for: Simple input output tasks (overhead is high)

ASYNCIO

Asyncio is used when handling thousands of tasks at once, like chat apps or web scraping.

Example: Fetching multiple URLs at the same time

import asyncio  

async def greet(name):
    await asyncio.sleep(1)  #delay
    print(f"Hello, {name}!")

async def main():
    tasks = [greet("Alice"), greet("Bob"), greet("Charlie")]
    await asyncio.gather(*tasks)  # Runs them all at once

asyncio.run(main())

Instead of waiting for one greeting to finish before starting the next, all are started together and switches whenever one is waiting.

Tasks run on a single thread but uses an event loop to switch between them whenever one encounters an await statement.

  • Best for: Handling thousands of requests, chat apps, real-time dashboards
  • Not good for: CPU-heavy tasks (single thread)

Threads vs. Multiprocessing vs. Asyncio

Threads vs. multiprocessing vs. asyncio
Threads vs. multiprocessing vs. asyncio

So next time your program feels slow, choose the right tool for concurrency!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top