🎓 A1Learner
🔍

Python The GIL & Choosing Threads

The GIL is the Global Interpreter Lock inside normal Python. The GIL lets only one thread run Python code at a time.

A thread that waits

Sleep stands in for a slow read or a network wait. The thread waits without holding the main thread back.

import threading
import time

def wait_and_greet():
    time.sleep(0.1)
    print("Wait finished")

t = threading.Thread(target=wait_and_greet)
t.start()
t.join()
print("Main continues")

Print in a fixed order

The fast thread finishes first here. The prints still follow the order you choose after join().

import threading
import time

results = {}

def worker(name, delay):
    time.sleep(delay)
    results[name] = name + " done"

slow = threading.Thread(target=worker, args=("slow", 0.2))
fast = threading.Thread(target=worker, args=("fast", 0.05))
slow.start()
fast.start()
slow.join()
fast.join()
print(results["slow"])
print(results["fast"])

Choose a process for computing

Heavy maths belongs in a process. Each process can truly compute at the same time.

from multiprocessing import Process

worker = Process(target=count_big)
worker.start()
worker.join()

Example

import threading
import time

results = {}

def fetch(name, delay):
    time.sleep(delay)
    results[name] = name + " page loaded"

first = threading.Thread(target=fetch, args=("first", 0.2))
second = threading.Thread(target=fetch, args=("second", 0.05))
first.start()
second.start()
first.join()
second.join()
print(results["first"])
print(results["second"])
print("Both pages are ready")

Key points

  • GIL: the Global Interpreter Lock inside normal Python.
  • The GIL lets only one thread run Python code at a time.
  • Use threads for waiting work, such as reading files or network replies.
  • Waiting work is called I/O-bound work.
  • I/O means input and output.
  • Use processes for heavy computing, such as maths on long lists.
  • Computing work is called CPU-bound work.
  • The CPU is the computer chip that runs code.
  • Each process has its own interpreter and its own GIL.
  • Python 3.13 adds an experimental free-threaded build with no GIL.

In this example, fetch stands in for loading a page. It sleeps to mimic the wait for a reply. It then stores a short message in the results dict. The second thread waits for less time and finishes first. The main code joins both threads before it prints. It prints first and then second, in that fixed order. The order comes from the print lines, not from speed.

Note

This course follows normal 3.12 behaviour.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Python Playground

Exercise

Your code spends most time waiting for network replies. What fits best in normal Python?