/*:#localized(key: "TasksAreNotThreads")
 # Tasks aren't threads

 There's a belief almost every developer carries in, and it's worth
 unlearning now, because everything above depends on it: **creating a task
 does not create a thread.**

 A **thread** is an expensive resource the operating system owns; it's the
 thing that actually runs instructions, and your machine only has a handful
 of cores to run them on. A **task** is just a unit of work *you* described.
 The two aren't the same size at all: you can make thousands of tasks, but
 there will only ever be a small number of threads.

 So Swift keeps a small **cooperative thread pool** (roughly **one thread per
 CPU core**) and *multiplexes* your tasks onto it. Many tasks take turns on a
 few threads. You don't get to pick which thread; the system schedules the
 work for you, using each task's **priority** as a hint for what to run first
 (more on priority in the chapter [Tasks and Cancellation](Tasks%20and%20Cancellation.playgroundchapter/Overview)).

 This is exactly why suspension matters. When a task hits an `await` and
 suspends, it **hands its thread back to the pool**, and some other task
 grabs that thread and makes progress. When your task's result is ready, it
 resumes on *whatever* pool thread is free next, which may be a **different**
 thread than it started on. (That's why "resume on some thread later," above,
 says *some*.)

 ```
 The pool has ~4 threads. You made 100 tasks.

 Task A runs on thread 2 ──await──▶ suspends, releases thread 2
                                        │
 Task B grabs thread 2 and runs ◀───────┘
    ...
 Task A's result is ready ──▶ resumes on whatever thread is free (maybe thread 0)
 ```

 The takeaway: don't imagine a fresh thread springing up behind every
 `Task { }`. Picture a few busy threads passing many tasks between them, each
 task letting go of its thread every time it `await`s.

 > **The classic model had a different temperament.** GCD also
 > runs on a thread pool, but if you *block* its threads (a `sync` wait, a
 > semaphore, a `Thread.sleep`) GCD tends to spin up **more** threads to
 > compensate, a problem called **thread explosion** that can balloon into
 > dozens of threads fighting over the same cores. The modern pool deliberately
 > refuses to: it stays capped at about core-count and relies on tasks
 > *suspending* (`await`) instead of *blocking*. That single difference
 > (suspend, don't block) is a big part of *why* the modern model exists, and
 > why calling a blocking API like `Thread.sleep` inside a task is a mistake
 > (the chapter [Tasks and Cancellation](Tasks%20and%20Cancellation.playgroundchapter/Overview) shows one holding a thread hostage).

 [Previous](@previous)  |  page 4 of 8  |  [Next: Awaiting Inside an Async Context](@next)
 */
