/*:#localized(key: "Deadlock")
 # Deadlock: waiting on yourself, forever

 A **deadlock** is when work stops permanently because tasks are waiting on
 each other in a circle, and no one can move. The simplest version needs only
 one queue and one word: `sync`.

 Recall that `sync` means *"run this block and don't return until it's
 finished."* Now the classic freeze. Running on the main thread, we `sync` onto
 the main queue:

 ```swift
 // ⚠️ DO NOT RUN THIS: it deadlocks the main thread forever.
 import Foundation

 DispatchQueue.main.sync {
     print("This line never runs.")
 }
 ```

 Walk the logic:

 1. You're on the main thread. You call `main.sync { ... }`.
 2. `sync` says: "I'll wait right here until that block finishes."
 3. But the block is scheduled to run on the **main queue**, which is the very
 thread now frozen inside `sync`, waiting.
 4. The main thread is waiting for the block; the block can't start until the
 main thread is free. Neither ever gives. **Frozen.**

 That's a circular wait with a single participant. The same trap springs
 whenever you `sync` onto **a serial queue you are already running on**:

 ```swift
 // ⚠️ DO NOT RUN THIS EITHER: same deadlock, different disguise.
 import Foundation

 let ledger = DispatchQueue(label: "ledger")   // serial

 ledger.sync {
     // We are now running *on* ledger...
     ledger.sync {          // ...and we ask it to run something and wait.
         print("Unreachable.")   // ledger is busy with us. Circular wait.
     }
 }
 ```

 We ran the racy example live because a wrong number is harmless. We are
 **not** running these, because a deadlock doesn't print anything; it just
 hangs the Playground page until you stop it manually. That is exactly why the
 rule is worth memorizing:

 **Never call `sync` targeting the queue you're already on. In particular,
 never `DispatchQueue.main.sync` from the main thread.**

 `async` doesn't have this problem: it hands the block over and returns
 immediately, so there's no one standing around waiting. When you need to
 bounce back to the main queue to update UI, it's `DispatchQueue.main.async`,
 always.

 [Previous](@previous)  |  page 6 of 9  |  [Next: Priority Inversion](@next)
 */
