The following code
DispatchQueue.main.async {
print(Thread.current)
DispatchQueue.global().sync {
print(Thread.current)
}
}
prints
<_NSMainThread: 0x60000059c140>{number = 1, name = main}
<_NSMainThread: 0x60000059c140>{number = 1, name = main}
Technically, global queue finds an idle thread to run the task, which might be the main thread.
Is there any explicit rule indicates when a task added to global queue will be performed on main thread?
So time consuming tasks put in the global queue wouldn't affect the main thread.
CodePudding user response:
A sync task will block your calling thread, which is the main thread in your code.
Even if the task in the global queue is dispatched to a global thread rather than the main thread. The main thread still needs to wait for the task to be completed.
In this case, GCD automatically optimizes the sync dispatch so that the task to be executed on the calling thread rather than let the calling thread waiting.
CodePudding user response:
You said:
Technically, global queue finds an idle thread to run the task, which might be the main thread.
Not quite. What’s going on is that if you dispatch synchronously (but not if you dispatch asynchronously), GCD may perform an optimization whereby the synchronously dispatched code will be run on the current thread, saving a costly context switch. As the sync
docs say:
As a performance optimization, this function executes blocks on the current thread whenever possible, with one exception: Blocks submitted to the main dispatch queue always run on the main thread.
This optimization is possible (other than when dispatching to the main queue) because the current thread will be blocked during a synchronous dispatch, anyways, so the costly context switch is often not needed/desired.
Is there any explicit rule indicates when a task added to global queue will be performed on main thread?
The question should be more generalized: When will the aforementioned performance optimization not be employed? As the above documentation states, if you do the converse (i.e., dispatch synchronously from a background queue to the main queue, or any queue that uses the main queue as its ultimate “target”), the optimization is turned off and it will not run the dispatched block on the current thread, but will always run it on the main thread. It does this because there are certain things that must happen on the main thread, so the optimization is disabled in this scenario.
There are other, less well documented, scenarios where this optimization may not be employed. One would be well advised to not overly rely on this optimization. Just rest assured that when GCD can, it will attempt to avoid costly context switches for synchronously dispatched tasks.