Deep Dive into GCD Dispatch Queues, sync/async Behavior, and RunLoop Interaction on iOS
This article explores the intricacies of Grand Central Dispatch on iOS, debunking common misconceptions about main thread and main queue execution, analyzing the internal handling of synchronous tasks, and demonstrating how run‑loop activation influences queue‑thread relationships through a series of code experiments.
The author, fascinated by multithreading, investigates Apple's lightweight GCD solution by reading libdispatch source code and attempts to create a series of detailed analyses.
Two fundamental concepts are highlighted: the difference between synchronous and asynchronous execution, and the distinction between queues and threads.
Misunderstood Concept: It is often believed that the main thread only executes tasks from the main queue and that the main queue runs exclusively on the main thread.
dispatch_queue_t mainQueue = dispatch_get_main_queue(); dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); dispatch_queue_set_specific(mainQueue, "key", "main", NULL); dispatch_sync(globalQueue, ^{ BOOL res1 = [NSThread isMainThread]; BOOL res2 = dispatch_get_specific("key") != NULL; NSLog(@"is main thread: %zd --- is main queue: %zd", res1, res2); });
Running this code yields YES for isMainThread and NO for the queue‑specific check, indicating that a synchronous task can execute on the main thread even when submitted to a global queue.
The implementation of dispatch_sync in libdispatch shows that a semaphore is used to block the calling thread until the task finishes:
static void _dispatch_sync_f_slow(dispatch_queue_t dq, void *ctxt, dispatch_function_t func) { _dispatch_thread_semaphore_t sema = _dispatch_get_thread_semaphore(); struct dispatch_sync_slow_s { DISPATCH_CONTINUATION_HEADER(sync_slow); } dss = { .do_vtable = (void*)DISPATCH_OBJ_SYNC_SLOW_BIT, .dc_ctxt = (void*)sema }; _dispatch_queue_push(dq, (void *)&dss); _dispatch_thread_semaphore_wait(sema); _dispatch_put_thread_semaphore(sema); // ... }
This explains why nested dispatch_sync calls can deadlock and suggests that, in most cases, the sync task runs on the current thread to avoid costly thread switches.
Further experiments set a specific key on the main queue and log the execution context from a background queue:
dispatch_queue_set_specific(mainQueue, "key", "main", NULL); dispatch_block_t log = ^{ printf("main thread: %zd", [NSThread isMainThread]); void *value = dispatch_get_specific("key"); printf("main queue: %zd", value != NULL); }; dispatch_async(globalQueue, ^{ dispatch_async(dispatch_get_main_queue(), log); }); dispatch_main();
The output ( NO for the thread check, YES for the queue check) shows that the main queue can execute on a non‑main thread when the application is launched as a script without the usual UIApplicationMain setup.
Adding the standard UIApplicationMain call and observing the run‑loop reveals that after the run‑loop starts, the main queue consistently runs on the true main thread, confirming that the run‑loop binds the main queue to the main thread.
To study run‑loop wake‑up mechanisms, the author compares CFRunLoopPerformBlock (which does not wake a sleeping run‑loop) with performSelector:onThread:withObject:waitUntilDone: (which wraps the task in a timer event that does wake the run‑loop). The experiment demonstrates that adding at least one source (e.g., a timer or port) is required for the run‑loop to stay alive and be awakened efficiently.
In conclusion, Apple's libdispatch largely retains its original design, but the system optimizes synchronous tasks by executing them on the current thread when possible, and the run‑loop’s activation determines whether the main queue is bound to the main thread.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.