Chapter 1 — Introduction: what concurrency really is

Concurrency is about dependencies, not threads

flowchart LR subgraph SEQ__Sequential__slow___ [\"Sequential (slow)\"] T1[toast: 3 min] --> C1[coffee: 4 min] --> E1[egg: 3 min] end subgraph CON__Concurrent__fast___ [\"Concurrent (fast)\"] T2[toast: 3 min] C2[coffee: 4 min] E2[egg: 3 min] T2 --> B2[butter toast] end
  • Concurrency is dealing with many things at once — structuring a program so independent work can
  • Parallelism is doing many things at once — literally executing on multiple cores simultaneously

Why the old way was so painful

Threads (the raw metal)

Grand Central Dispatch (queues)

// The GCD era — functional, but full of traps.
DispatchQueue.global().async {
    let data = loadData()                 // background work
    DispatchQueue.main.async {            // hop back to the main thread for UI
        self.label.text = data.title
    }
}
  1. Callback pyramids. Every asynchronous step is a nested closure. Three sequential network calls
  2. No enforced structure. Nothing connects the background work to the UI hop. If the background
  3. No safety net for data races. GCD will happily let you touch self.items from two queues at
flowchart TB A["loadUser { user in"] --> B[" loadPosts(user) { posts in"] B --> C[" loadComments(posts) { comments in"] C --> D[" DispatchQueue.main.async { update UI }"] D --> E[" } // and error handling in each level…"]

Modern Swift concurrency (async/await, 2021→)

  1. async/await lets asynchronous code read like straight-line code. The three-call pyramid
  2. Structured concurrency ties child work to a scope with automatic waiting and cancellation, so
  3. Actors, Sendable, and Swift 6 checking make data races a compile-time error. The category

The three ideas this book is built on

flowchart LR I1["await = maybe suspend
(not block a thread)"] --> BOOK I2["structured concurrency
= work bound to scope"] --> BOOK I3["isolation + Sendable
= who touches what"] --> BOOK["A model you can
reason about"]

What a "data race" actually is

  1. two or more pieces of code access the same memory concurrently,
  2. at least one of those accesses is a write, and
  3. there's no synchronization ordering them.

What this book covers, and what it assumes

  • Part Iasync/await, the Task type, and cancellation. After this you can write and run
  • Part II — structured concurrency (async let, task groups), continuations (to bridge the old
  • Part III — actors (safe shared state), their reentrancy pitfall, the main actor and global
  • Part IV — turning on Swift 6's strict checking and fixing what it finds, Swift 6.2's

A note on mindset

What we set up in this chapter

  • Reframed concurrency as describing dependencies between pieces of work, distinct from parallelism
  • Traced the three eras — threads → GCD → async/await — and named the chronic problems of the old
  • Introduced the three ideas the book is built on: await is a possible suspension, not a block;
  • Defined the enemy precisely — a data race (concurrent access, at least one write, no
  • Set the mindset: the Swift 6 compiler is a collaborator, and its diagnostics are lessons, not

Mental model to take away

  • Concurrency is structure, not threads. You describe what can overlap and what must wait; the
  • The old tools let you write the bug; modern Swift is designed so the bug doesn't compile.
  • Hold three ideas above everything: await may suspend (not block), **structured concurrency ties
  • A data race — the defining hazard — is exactly what Swift 6 eliminates at compile time. Treat its