iOS Dispatch_sync 阻塞线程的原因

大家的知道在主队列上使用dispatch_sync(),

- (void)testSyncMainThread {
    
    dispatch_queue_t main = dispatch_get_main_queue();
    NSLog(@"*********1");
    dispatch_sync(main, ^(){
            NSLog(@"*********2");
    });
    NSLog(@"*********3");
}

会造成线程阻塞,但是查找网上说的原因,发现基本上说法都是一样的,感觉不是不太好理解,

我查看一下API, 

/*!

 * @function dispatch_sync

 *

 * @abstract

 * Submits a block for synchronous execution on a dispatch queue.

 *

 * @discussion

 * Submits a workitem to a dispatch queue like dispatch_async(), however

 * dispatch_sync() will not return until the workitem has finished.

 *

 * Work items submitted to a queue with dispatch_sync() do not observe certain

 * queue attributes of that queue when invoked (such as autorelease frequency

 * and QOS class).

 *

 * Calls to dispatch_sync() targeting the current queue will result

 * in dead-lock. Use of dispatch_sync() is also subject to the same

 * multi-party dead-lock problems that may result from the use of a mutex.

 * Use of dispatch_async() is preferred.

 *

 * Unlike dispatch_async(), no retain is performed on the target queue. Because

 * calls to this function are synchronous, the dispatch_sync() "borrows" the

 * reference of the caller.

 *

 * As an optimization, dispatch_sync() invokes the workitem on the thread which

 * submitted the workitem, except when the passed queue is the main queue or

 * a queue targetting it (See dispatch_queue_main_t,

 * dispatch_set_target_queue()).

 *

 * @param queue

 * The target dispatch queue to which the block is submitted.

 * The result of passing NULL in this parameter is undefined.

 *

 * @param block

 * The block to be invoked on the target dispatch queue.

 * The result of passing NULL in this parameter is undefined.

 */

结合API,我的理解:

第一步:当代码执行到 dispatch_sync()时,会首先把dispatch_sync()函数放到当前线程的队列(就是主队列中),而且这个线程并不会立即返回,而是会等待block中的任务都完成时才会返回,

第二步:再把block中的任务依次放到主队列中等待执行,

由于是同步执行,而且block中的任务在主队列的线性表中的前面有个dispatch_sync()等待完成,而dispatch_sync()的完成又依赖于block的执行完成,就这样造成了死锁。

最后:在其他队列上模拟这种死锁情况

 dispatch_queue_t lwMainQueue = dispatch_queue_create("lw.queue", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(lwMainQueue, ^{
        NSLog(@"*********1");
        dispatch_sync(lwMainQueue, ^{NSLog(@"*********2");
        });
    NSLog(@"*********3");
    });

效果是一样的

原文地址:https://www.cnblogs.com/liuwenqiang/p/10943840.html