advanced

Memory Model & GIL

8 min readLast updated: 2026-07-12

Overview

Learn how Python manages object allocation, performs garbage collection, and structures thread tasks with the GIL.

Learning Objectives

  • Learn reference counting and generational garbage collection.
  • Understand the Global Interpreter Lock (GIL) limits.
  • Isolate heavy calculations using multiprocessing.

Concept Explanation

CPython manages memory using reference counting. Objects are freed immediately when their reference count drops to 0. Generational garbage collection runs periodically to clean circular references. The GIL (Global Interpreter Lock) is a lock that serializes execution, allowing only one thread to execute Python bytecode at a time.

Code Examples

Example 1 — Basics

This example introduces the fundamental syntax and concepts.

python
import sys
x = []
print(sys.getrefcount(x) - 1)

Example 2 — Everyday Usage

This example demonstrates a realistic scenario handling business parameters.

python
# Generational cyclic gc runs automatically
import gc
gc.collect() # Manually trigger cycle cleanup

Example 3 — Advanced Example

This example shows clean, production-grade code structure following senior development standards.

python
from multiprocessing import Process

def heavy_calc(data):
    # Runs in separate process, bypassing GIL limits
    return sum(x * x for x in data)

if __name__ == '__main__':
    p = Process(target=heavy_calc, args=(range(1000),))
    p.start()
    p.join()

Visual Flow

The following execution flow represents the step-by-step evaluation inside the interpreter:

text
Request GIL → Run Thread Bytecode → Hit I/O or sleep timer → Release GIL → Thread switch

Common Mistakes

Review these common pitfalls when working with this topic:

  • Expecting multithreading to speed up CPU-heavy tasks.
  • Creating circular dependencies that delay garbage collection.
  • Assuming the GIL makes application code thread-safe.
  • Neglecting processing guards when launching child processes.

Best Practices

Enforce these Pythonic best practices in your codebase:

❌ Don't
python
# CPU calculation multithreading
t1 = Thread(target=cpu_heavy)
t2 = Thread(target=cpu_heavy)
✅ Do
python
# CPU calculation multiprocessing
p1 = Process(target=cpu_heavy)
p2 = Process(target=cpu_heavy)

Performance Notes

Keep these optimization guidelines in mind for performance-sensitive hotpaths:

  • The GIL is released during block operations like file I/O, network requests, and database queries.
  • Reference counting occurs in O(1) time, while cyclic garbage collection runs periodically in O(N) time.

Quick Revision

Use these key summaries for last-minute revision:

  • CPython uses reference counting to free memory.
  • Cyclic GC handles self-referencing loops.
  • GIL restricts concurrency of bytecodes.
  • GIL is released automatically during file I/O.
  • Multiprocessing utilizes separate CPU cores.