It is all related to main queue. There are 4 permutations.
i) Serial queue, dispatch async : Here the tasks will execute one after the other, but the main thread(effect on UI) will not wait for return
ii) Serial queue, dispatch sync: Here the tasks will execute one after the other, but the main thread(effect on UI) will show lag
iii) Concurrent queue, dispatch async : Here the tasks will execute in parallel and the main thread(effect on UI ) will not wait for return and will be smooth.
iv) Concurrent queue, dispatch sync : Here the tasks will execute in parallel, but the main thread(effect on UI) will show lag
Your choice of concurrent or serial queue depends on if you need an output from a previous task for the next one. If you depend on the previous task, adopt the serial queue else take concurrent queue.
And lastly this is a way of penetrating back to the main thread when we are done with our business :
DispatchQueue.main.async {
// Do something here
}