Python offers three concurrency models, and choosing correctly depends mainly on whether your work is I/O-bound or CPU-bound — a decision heavily shaped by the GIL (which prevents threads from running Python code in parallel).
The three models
threading → multiple threads, ONE process. GIL-limited for CPU.
multiprocessing → multiple PROCESSES, each its own interpreter/GIL → true parallelism.
asyncio → single thread, cooperative coroutines yielding at await points.
