Skip to content

03 — Queue

rebeloper edited this page Jul 12, 2026 · 1 revision

🍽️ Intuition

Not every restaurant runs its order line the same way.

Some kitchens insist on one order at a time — the next order doesn't even start until the current one is fully cooked and out the door.

Other kitchens let several orders cook at once — as soon as an order lands, whichever chef 🧑‍🍳 is free grabs it, no matter what else is already on the stove.

  • One order line, one chef, strict order → serial
  • One order line, several chefs, orders grabbed whenever a chef is free → concurrent

👉 Both are still "order lines." The difference is how many chefs are allowed to pull from the line at the same time.


🧠 What It Means In Swift

DispatchQueue comes in two flavors, and the flavor is set when you create the queue:

  • Serial queue — the default. Only one block runs at a time, and blocks run in the exact order they were submitted. Block 2 does not start until Block 1 finishes.
  • Concurrent queue — created with attributes: .concurrent. Multiple blocks can run at the same time, pulled from GCD's shared thread pool. Blocks still start in submission order, but they can finish in any order, since one might take longer than another.
let serial = DispatchQueue(label: "serial")
let concurrent = DispatchQueue(label: "concurrent", attributes: .concurrent)

👉 "Queue" doesn't tell you how many workers can pull from it at once — you have to know whether it's serial or concurrent.

One important note: serial vs. concurrent describes the queue, not the thread pool. Both queue types still hand their blocks off to GCD's same shared, system-managed pool of chefs from Chapter 1. A serial queue just refuses to hand off a second block until the first one is done.


📊 ASCII Diagram

SERIAL QUEUE — one line, one chef, strict order 🧾

📋 Order 1 ──┐
📋 Order 2 ──┼──> 🧾 Serial Queue ──> 🧑‍🍳 ──> done, in order: 1, 2, 3
📋 Order 3 ──┘

Order 2 doesn't even start until Order 1 is fully done.


CONCURRENT QUEUE — one line, several chefs, order not guaranteed 🧾

📋 Order A ──┐
📋 Order B ──┼──> 🧾 Concurrent Queue ──> 👨‍🍳 (Order A)
📋 Order C ──┘                        └──> 👩‍🍳 (Order B)
                                       └──> 🧑‍🍳 (Order C)

All three can be cooking at once. Whichever finishes first, finishes first.

💻 Tiny Swift Example

let serial = DispatchQueue(label: "serial")
let concurrent = DispatchQueue(label: "concurrent", attributes: .concurrent)

serial.async { print("Order 1 🍔") }
serial.async { print("Order 2 🍕") }  // guaranteed to run after Order 1

concurrent.async { print("Order A 🍔") }
concurrent.async { print("Order B 🍕") }  // may run before or after Order A

👉 On the serial queue, "Order 1" always prints before "Order 2." On the concurrent queue, "Order A" and "Order B" might print in either order — or practically at the same time.


🔄 vs. Swift Concurrency

Swift Concurrency has direct analogues for both queue types:

  • A serial queue behaves like an actor's serial executor — an actor only ever runs one task's code at a time, in isolation, which is exactly how a serial queue protects its blocks from overlapping.
  • A concurrent queue behaves like a bunch of independent unstructured Tasks — each one runs on its own, in parallel, with no ordering guarantee between them.

👉 If you've used an actor and wondered why its methods never seem to run at the same time as each other, that's the same guarantee a serial queue has always given you.


🧸 Memory Sentence

A queue is the order line that decides who gets cooked next.


⚠️ Analogy Limit

A real order line is strictly FIFO — first order in, first order out, whether it's serial or concurrent.

GCD's queues aren't quite that simple:

  • Priority — higher QoS work can be scheduled ahead of lower-priority work already waiting
  • System-level optimizations — GCD can reorder, batch, or delay work based on overall system load, not just submission order

So "the order line" captures submission order and worker count — but not the priority and scheduling logic GCD applies underneath.


✅ Check Your Understanding

What's the key difference between a serial queue and a concurrent queue — and what does that difference guarantee (or not guarantee) about the order your work finishes in?

Clone this wiki locally