iOS Dispatch_sync 阻塞線程的緣由

你們的知道在主隊列上使用dispatch_sync(),async

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

 

會形成線程阻塞,可是查找網上說的緣由,發現基本上說法都是同樣的,感受不是不太好理解,函數

我查看一下API, this

/*!spa

 * @function dispatch_sync線程

 *code

 * @abstractorm

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

 *隊列

 * @discussionget

 * 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");
    });

效果是同樣的

相關文章
相關標籤/搜索