Skip to content

01 — Why GCD Exists

rebeloper edited this page Jul 12, 2026 · 2 revisions

🍽️ Intuition

Imagine a restaurant before it had any real staffing system.

Every single order gets its own personal chef 🧑‍🍳, hired on the spot.

  • Order comes in → hire a chef 👋

  • Chef cooks the order 🍔

  • Order is done → fire the chef 👋💨

  • Next order comes in → hire a new chef again...

  • Ten orders at once? Ten chefs, hired and fired on the spot 😵

  • A thousand orders? The restaurant collapses under its own hiring paperwork

👉 This is what programming looked like before GCD: one thread, manually created, per unit of work.


🧠 What It Means In Swift

Before GCD existed (pre-2009, pre-iOS 4, pre-Mac OS X Snow Leopard), concurrency meant managing threads by hand:

  • Thread / NSThread — create, configure, and start a thread yourself
  • pthread — the raw POSIX thread API, even lower-level

With these tools, you were the hiring manager:

  • You decided how many threads to create
  • You sized the thread pool yourself, guessing at the "right" number
  • Too few threads → work piles up, the app feels sluggish
  • Too many threads → wasted memory, and the CPU burns time just switching between threads instead of doing work

There was no shared system smart enough to say "let's not hire a new chef for every order."

Then, in 2009, Apple introduced Grand Central Dispatch (GCD).

GCD's big idea: stop managing threads yourself. Instead:

  • You submit blocks of work to a queue 🧾
  • The system owns a shared, managed thread pool 👨‍🍳👩‍🍳
  • The system decides how many threads to actually use, based on available cores and system load

You stopped being the hiring manager. The kitchen now manages a shared team of chefs for you.


📊 ASCII Diagram

BEFORE GCD — Hire a chef per order 😵

📋 Order 1 → hire 🧑‍🍳 → serve → fire 💨
📋 Order 2 → hire 🧑‍🍳 → serve → fire 💨
📋 Order 3 → hire 🧑‍🍳 → serve → fire 💨

💸 Constant hiring/firing overhead, no shared plan


AFTER GCD — Submit to a queue, staff is managed 🎉

📋 Order 1 ──┐
📋 Order 2 ──┼──> 🧾 Queue ──> 👨‍🍳👩‍🍳 (shared, system-managed pool)
📋 Order 3 ──┘

💡 The system decides how many chefs are actually needed

💻 Tiny Swift Example

You used to have to spin up and manage threads yourself:

// Old style — manual thread management (no longer necessary)
let thread = Thread {
    print("Order 1 🍔")
}
thread.start()

With GCD, you just submit the work — the system manages the threads:

// GCD: just submit work, the system manages the threads
DispatchQueue.global().async {
    print("Order 1 🍔")
}

👉 No hiring. No firing. Just hand the order to the queue.


🔄 vs. Swift Concurrency

GCD solved one problem really well: thread management. You no longer had to hand-size a thread pool — the system did it for you.

Swift Concurrency (introduced in 2021) runs on a similarly system-managed, cooperative thread pool — but it exists to solve a different, higher-level set of problems:

  • Structured task lifecycle — tasks have clear parents, children, and scopes
  • Cancellation — cancellation propagates automatically through a task tree
  • Data-race safety — the compiler checks for unsafe shared mutable state

👉 GCD answers "who runs this work?" Swift Concurrency answers "how do I structure, cancel, and safely share data across this work?"


🧸 Memory Sentence

GCD replaced hand-hiring a chef per order with a shared team of chefs the kitchen manages for you.


⚠️ Analogy Limit

A restaurant's staff size is usually something a manager sets and adjusts occasionally.

GCD's thread pool is far more dynamic than that:

  • It grows and shrinks in real time, per task
  • It's driven by Quality of Service (QoS) and current system load, not a fixed headcount

So "a shared team of chefs" captures the shift in responsibility — but not how fluid and automatic the actual sizing really is.


✅ Check Your Understanding

If every order got its own hand-hired, hand-fired chef, what happens to the restaurant as order volume grows — and why doesn't that scale?

Clone this wiki locally