/*:#localized(key: "BlockingWithSync")
 # `sync`: block until it's done

 The opposite of `async` is **`sync`**. It submits the closure and then
 **blocks the calling thread** until that closure has finished. Control
 doesn't come back to you until the work is done.
 */
//#-editable-code
import Foundation

print("1️⃣ Before")

DispatchQueue.global().sync {
    Thread.sleep(forTimeInterval: 0.5)
    print("2️⃣ Inside the sync block")
}

print("3️⃣ After: this waited for the block")
//#-end-editable-code
/*:#localized(key: "BlockingWithSync-2")
 **Watch it run:** this time you get a clean `1️⃣ 2️⃣ 3️⃣`. The `sync` call parked
 the main thread until the block finished, so `3️⃣` couldn't print until `2️⃣`
 did. Notice you gained nothing here: you moved work to a background queue but
 then *waited* for it on the main thread. The main thread was blocked the
 whole time anyway.

 That's the key lesson: **`sync` off the main thread rarely buys you
 anything**, because the point of moving work off the main thread is to *not*
 wait for it. You almost always want `async`.
 
 `sync` has narrow, deliberate uses (like briefly reading a value from a serial
 queue that guards shared state); reaching for it to "run background work" is
 usually a mistake.

 * callout(Danger): Never call `DispatchQueue.main.sync { }` from the main
 thread. The main thread would block waiting for the main queue, which can't
 run the block until the main thread is free. It waits for itself forever.
 That's a **deadlock**, and it freezes your app hard. Don't run that; just
 know it exists. Deadlocks get a proper treatment in the chapter
 [Concurrency Hazards](Concurrency%20Hazards.playgroundchapter/Overview).

 [Previous](@previous)  |  page 4 of 9  |  [Next: Serial vs. Concurrent: Order and Overlap](@next)
 */
