Concurrency

Concurrency in Python allows multiple tasks to be executed in overlapping periods, rather than sequentially. This can improve the performance of a program, especially when tasks involve waiting for I/O operations like reading from a file, network communication, or database operations. Concurrency in Python can be achieved through threads, multiprocessing, and asynchronous programming.

Concurrency in Python vs. Go

Unlike Go, which has built-in support for concurrency through goroutines and channels, Python does not have a direct equivalent. However, Python provides several modules to achieve concurrency:

  1. threading Module: Used for concurrent execution of code by creating threads.
  2. multiprocessing Module: Used for concurrent execution of code by creating separate processes.
  3. asyncio Module: Used for asynchronous programming, which is especially useful for I/O-bound tasks.

Examples

Using threading Module

The threading module allows you to run multiple threads (smaller units of a process) concurrently.

import threading
import time

def print_numbers():
    for i in range(1, 6):
        time.sleep(1)
        print(f"Number: {i}")

def print_letters():
    for letter in 'abcde':
        time.sleep(1.5)
        print(f"Letter: {letter}")

# Create threads
thread1 = threading.Thread(target=print_numbers)
thread2 = threading.Thread(target=print_letters)

# Start threads
thread1.start()
thread2.start()

# Wait for both threads to complete
thread1.join()
thread2.join()

print("Done!")

Using multiprocessing Module

The multiprocessing module allows you to run multiple processes concurrently, which can be beneficial for CPU-bound tasks.

import multiprocessing
import time

def print_numbers():
    for i in range(1, 6):
        time.sleep(1)
        print(f"Number: {i}")

def print_letters():
    for letter in 'abcde':
        time.sleep(1.5)
        print(f"Letter: {letter}")

# Create processes
process1 = multiprocessing.Process(target=print_numbers)
process2 = multiprocessing.Process(target=print_letters)

# Start processes
process1.start()
process2.start()

# Wait for both processes to complete
process1.join()
process2.join()

print("Done!")

Using asyncio Module

The asyncio module is used for writing asynchronous code. It allows you to define coroutines, which can be paused and resumed, making it useful for I/O-bound tasks.

import asyncio

async def print_numbers():
    for i in range(1, 6):
        await asyncio.sleep(1)
        print(f"Number: {i}")

async def print_letters():
    for letter in 'abcde':
        await asyncio.sleep(1.5)
        print(f"Letter: {letter}")

async def main():
    task1 = asyncio.create_task(print_numbers())
    task2 = asyncio.create_task(print_letters())

    await task1
    await task2

asyncio.run(main())