Concurrency

Concurrency allows you to handle multiple tasks at once, which is crucial for improving efficiency and responsiveness in programs. Python provides various models for concurrency such as Threading, Mul

Concurrency Methods

Feature
Description
Use Case
Pros
Cons

Threading

Runs multiple threads in the same memory space.

I/O-bound tasks like network calls, file reading.

1. Lightweight 2. Simple syntax

1. Blocked by GIL 2. Not ideal for CPU-heavy tasks

GIL (Global Interpreter Lock)

A lock that prevents multiple threads from executing bytecodes simultaneously.

Restricts Python's multi-threading to one thread at a time.

1. Simplifies memory management

1. Limits CPU-bound multi-threading

Multiprocessing

Launches separate processes, each with its own memory space.

CPU-bound tasks such as data crunching, video rendering.

1. True parallelism 2. Bypasses GIL

1. Higher memory use 2. More overhead due to inter-process communication

AsyncIO

Cooperative multitasking using async and await.

Efficient for I/O-heavy operations like socket or web communication.

1. Scalable 2. Low memory footprint

1. Learning curve 2. Not for CPU-heavy tasks

ThreadPoolExecutor

High-level interface for threading via concurrent.futures.

Parallelize simple I/O tasks.

1. Easy to use 2. Manages threads efficiently

1. GIL still applies

ProcessPoolExecutor

High-level interface for multiprocessing.

Parallelize CPU-heavy computations.

1. Simple API 2. Avoids GIL

1. Slower startup 2. High memory usage

Thread-safe Queue

Queue class from queue module, useful for thread/process communication.

Sharing data between workers.

1. Safe and reliable data exchange

1. Slight overhead

aiohttp

Async HTTP client for asyncio-based applications.

High-performance async web scraping and APIs.

1. Built-in connection pooling 2. Easy coroutine integration

1. Async-only, requires different architecture


Comparison: AsyncIO vs Threading vs Multiprocessing

Feature
AsyncIO
Threading
Multiprocessing

Best For

I/O-bound & high concurrency

I/O-bound tasks

CPU-bound heavy computation

Memory Usage

Low

Medium

High

GIL Affected?

No

Yes

No

Parallelism

Cooperative (non-blocking)

Pseudo-parallelism (blocked by GIL)

True parallelism

Complexity

Medium to High

Low

Medium


Code Samples

import threading
import time

def download_file(file_id):
    print(f"Downloading file {file_id}...")
    time.sleep(2)
    print(f"Finished downloading file {file_id}")

threads = []
for i in range(3):
    t = threading.Thread(target=download_file, args=(i,))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

# ===== Output ==========
"""
Downloading file 0...
Downloading file 1...
Downloading file 2...
Finished downloading file 0
Finished downloading file 1
Finished downloading file 2
"""
from concurrent.futures import ThreadPoolExecutor

def greet(name):
    return f"Hello, {name}!"

names = ["Alice", "Bob", "Charlie"]

with ThreadPoolExecutor() as executor:
    results = executor.map(greet, names)
    for result in results:
        print(result)

# output
"""
Hello, Alice!
Hello, Bob!
Hello, Charlie!
"""

Last updated