The Global Interpreter Lock protects the interpreter’s internal state. Threads still help with I/O waits because the lock is released while they block, but CPU-bound Python code in threads does not run in parallel. See free-threading.