You’re the Expert!

pynfinity

Build mountain with each pebble 🧗

Topics | Stepping Stones

📚 Guides

🌍 Pebbles & Contributions

✍️ Write a Post
🗺️ Folium Maps
🗺️ Folium Maps
⏳ Time Series Resampling
⏳ Time Series Resampling
📦 Dataclasses
📦 Dataclasses
🔁 Itertools
🔁 Itertools
🗄️ SQLAlchemy Basics
🗄️ SQLAlchemy Basics
📄 JSON Handling
📄 JSON Handling
🖥️ OS Module
🖥️ OS Module
🔢 NumPy Arrays
🔢 NumPy Arrays
⚡ Generators
⚡ Generators
🐼 Pandas DataFrames
🐼 Pandas DataFrames
🎛️ Multiprocessing
🎛️ Multiprocessing
⚡ FastAPI Endpoints
⚡ FastAPI Endpoints
📜 List Comprehensions
📜 List Comprehensions
🪵 Logging
🪵 Logging
🚀 Streamlit Apps
🚀 Streamlit Apps
🧪 Pytest Testing
🧪 Pytest Testing
🧹 Data Cleaning with Dropna
🧹 Data Cleaning with Dropna
🧠 TensorFlow Basics
🧠 TensorFlow Basics
🌲 Git Basics
🌲 Git Basics
📦 Virtual Environments
📦 Virtual Environments
🏷️ Type Hinting
🏷️ Type Hinting
🚪 Context Managers
🚪 Context Managers
🛠️ Functools
🛠️ Functools
🤖 Scikit-Learn Linear Regression
🤖 Scikit-Learn Linear Regression
🧩 Regular Expressions
🧩 Regular Expressions
🎀 Decorators
🎀 Decorators
📸 OpenCV Image Reading
📸 OpenCV Image Reading
💻 Argparse CLI
💻 Argparse CLI
✨ Jupyter Magic Commands
✨ Jupyter Magic Commands
🛡️ Pydantic Models
🛡️ Pydantic Models
🕸️ Web Scraping with BeautifulSoup
🕸️ Web Scraping with BeautifulSoup
📊 Interactive Plots with Plotly
📊 Interactive Plots with Plotly
📚 Collections Module
📚 Collections Module
📝 NLTK Tokenization
📝 NLTK Tokenization
λ Lambda Functions
λ Lambda Functions
📉 Matplotlib Plotting
📉 Matplotlib Plotting
🔥 Seaborn Heatmaps
🔥 Seaborn Heatmaps
🧵 Multithreading
🧵 Multithreading
⏳ AsyncIO
⏳ AsyncIO
🔥 PyTorch Tensors
🔥 PyTorch Tensors
⚙️ Sys Module
⚙️ Sys Module
☁️ AWS S3 with Boto3
☁️ AWS S3 with Boto3
🥒 Pickle Serialization
🥒 Pickle Serialization
🕸️ NetworkX Graphs
🕸️ NetworkX Graphs
➗ Math Module
➗ Math Module
🔍 Exploratory Data Analysis (EDA)
🔍 Exploratory Data Analysis (EDA)
📊 CSV Processing
📊 CSV Processing
🐳 Dockerfiles
🐳 Dockerfiles
📉 Statsmodels OLS
📉 Statsmodels OLS
+ New Post

🧵 Multithreading and Semaphores in Python

Multithreading allows a program to run multiple operations concurrently. However, in Python, the Global Interpreter Lock (GIL) limits true parallelism for CPU-bound tasks, making threading most effective for I/O-bound tasks.


🧵 The threading Module

The threading module allows you to create and manage threads.

import threading
import time

def worker(name):
    print(f"{name} starting")
    time.sleep(1)
    print(f"{name} exiting")

t1 = threading.Thread(target=worker, args=("Thread-1",))
t2 = threading.Thread(target=worker, args=("Thread-2",))

t1.start()
t2.start()

t1.join() # Wait for completion
t2.join()

🚦 Synchronization Primitives

When threads share data, race conditions can occur. Synchronization primitives help prevent this.

🔒 Locks

A Lock ensures that only one thread can access a resource at a time.

lock = threading.Lock()
counter = 0

def increment():
    global counter
    with lock:
        counter += 1

🚩 Semaphores

A Semaphore manages an internal counter. It allows a fixed number of threads to access a resource simultaneously.

import threading
import time

semaphore = threading.Semaphore(2) # Allow 2 threads at a time

def access_resource(id):
    print(f"Thread {id} waiting")
    with semaphore:
        print(f"Thread {id} acquired semaphore")
        time.sleep(2)
    print(f"Thread {id} released semaphore")

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

This is useful for limiting connections to a database or API.


🏊 ThreadPoolExecutor

The concurrent.futures module provides a high-level interface for asynchronously executing callables.

from concurrent.futures import ThreadPoolExecutor

def task(n):
    return n * n

with ThreadPoolExecutor(max_workers=3) as executor:
    results = executor.map(task, range(5))

print(list(results)) # [0, 1, 4, 9, 16]

📝 Summary

  • GIL: Python's Global Interpreter Lock prevents multiple native threads from executing Python bytecodes at once.
  • I/O Bound: Threading is great for network requests, file I/O.
  • Locks: Prevent race conditions by ensuring mutual exclusion.
  • Semaphores: Control access to a resource with limited capacity.
  • ThreadPoolExecutor: Easier management of a pool of threads.

Created with ❤️ by Pynfinity



Pynfinity
Install Pynfinity Add to home screen for the best experience