Python GIL: Understanding Locking and Performance

How does multi threading work in python if GIL locks everything? TL;DR: The trick is when the GIL actually holds the lock and when it lets go. Our code usually does two kind of tasks - 1. CPU-bound (thinking) - Heavy stuff like parsing large JSON, resizing images. This needs the GIL. 2. I/O-bound (waiting) - Waiting for a database, an API call, S3, etc. This does not need the GIL. How it works in Python? Lets take an example of a thread making an API call using requests.get(). -> Python sends the request -> Now it’s just waiting to get a response. At this point, Python knows there’s nothing to “compute”, so it releases the GIL automatically. While Thread A is waiting on the network, Thread B can takeover the GIL and handle another user request. When the response comes, thread A reacquires the GIL, parses the response and completes the API call. This is why Django, Flask, and FastAPI servers can handle hundreds of requests at once. Fun fact - In a typical web request: ~90% of the time is spent waiting (DB, APIs, storage) ~10% is actual computation The GIL makes Python slower for heavy computation. But in most backend systems, database query is usually much slower than any GIL switching delay. Have you ever actually hit a performance issue where the GIL was the real problem? I am trying to learn Python Internals in detail and will share my learnings. Do follow along and tell your experiences in comments. #Python #PythonInternals #SoftwareEngineering #BackendDevelopment

  • diagram

To view or add a comment, sign in

Explore content categories