DispatchQueue.main.sync on the main thread

Concurrency Junior Swift 5.0+ iOS 17+ Reviewed By Alok Singh

Predict the output

This runs in viewDidLoad (on the main thread). What happens?

print("1")
DispatchQueue.main.sync {
    print("2")
}
print("3")
Options
Hint 1 of 1

What is the main thread doing while sync waits?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: C 1, then the main thread deadlocks and libdispatch usually crashes the app

Correct. sync waits on the main queue from the main queue.

Why not the others?
  • A 1, 2, 3. The closure needs the main thread, which is blocked waiting for it.
  • B 1, 3, 2. That is what main.async would print; sync waits.
  • D 1, then the app hangs silently forever. It is a deadlock, but GCD detects this case and usually traps instead of hanging.

30-second answer

It deadlocks. sync waits for the closure to finish, but the closure can only run on the main thread, which is busy waiting. libdispatch usually detects this and crashes the app. main.async just queues the closure and returns, so it is safe from any thread.

Practise saying it · 30 s. No recording, just a timer

Explain why main.sync from main deadlocks.

Say your answer out loud, then check which of these points you covered:

  • sync waits for the closure
  • closure needs the busy main thread
  • use async or MainActor

Deep dive

The same applies to any serial queue: never sync onto the queue you are running on.

main.async from the main thread runs the closure on a later run-loop pass.

In async code use await MainActor.run { } or a @MainActor function instead.

MainActor.assumeIsolated asserts you are already on main without hopping.

Common mistakes

  • Using sync to 'make sure' UI code runs on main.
  • Calling sync on a serial queue from inside its own work item.
  • Using main.async inside async functions.

Senior take & follow-ups

Seniors explain the wait cycle in one sentence and offer the modern alternative.

Follow-up questions

Think of your answer first, then open the hint.

  1. Why does sync to a different serial queue work?

    Show hint

    That queue's thread isn't the one waiting.

  2. How do you run code on main from async code?

    Show hint

    Call a @MainActor function with await.

Suggest a fix if something here is wrong or out of date.