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

效果是一樣的

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM