Is the mainQueue serial or concurrent?
I’m here with another popular iOS interview question that I get asked frequently.
👨🏻🏫 ”Is the mainQueue serial or concurrent?”
Short answer: the main queue is serial. 😀
If you think about the mainQueue, it is designed for the UI. If you want to make changes on the UI, their order you dispatched asynchronous action in the mainQueue still matters. For instance, when you run an animation or update labels, images, or navigation, you don’t want those updates racing each other. So the main queue works like one-after-another: each task must complete before the next task is able to start. That’s exactly what a serial queue gives you. On the other hand the GlobalQueues are in general concurrent with tasks with respect to each other’s completion. Because you can dispatch offline things of main thread and do something maybe super intensive (networking, decoding, file I/O etc.) and then when it finished you can update the UI. Those are usually concurrent on parallel depending on the needs.
A quick mental model that helps in interviews:
Also don’t mix up serial/concurrent with sync/async. Those are different axes:
Serial vs concurrent → how the queue runs tasks (one-by-one vs overlapping)
sync vs async → whether the caller waits
sync→ wait until that work finishesasync→ submit the work and continue
So DispatchQueue.main.async { ... } still runs on the serial main queue. Async only means “don’t block the caller while waiting to schedule it.” It does not mean “run this in the background.”
That distinction also explains a classic crash/freeze: calling DispatchQueue.main.sync while you are already on the main thread. The main queue is waiting for the sync block to finish but the sync block can’t start until the main queue is free, it is deadlock. Prefer main.async for UI updates and if you must use sync, never sync a queue against itself.
Where does this land with modern Swift?
Actors protect mutable state by serializing access, one caller at a time. An actor gives us its own isolation domain and that work usually runs off the main thread unless the actor is main-actor isolated. So conceptually it’s similar energy to a serial queue: controlled, ordered access. But the main actor / main queue remains special because UIKit/SwiftUI UI updates still need that serial main-thread world.
Interview takeaway: Main queue = serial, UI-bound, order matters. Global queues = concurrent, good for heavy work. Sync/async is about waiting, not about which queue you are on.


