dispatch_sync

dispatch_async 函數的“async”意味著“非同步”(asynchronous),就是將指定的Block“非同步”地追加到指定的Dispatch Queue中。dispatch_async函數不做任何等待。

屏幕快照 2016-03-01 下午10.16.31.png

既然有“async”,當然就有“sync”,即 dispatch_sync函數。它意味著“同步”(synchronous),也就是將指定的Block" 同步"追加到指定的Dispatch Queue中。在追加Block結束之前,dispatch_sync 函數會一直等待。


屏幕快照 2016-03-01 下午10.20.29.png
dispatch_sync函數簡單,容易引起問題。即死鎖。

例如如果在主線程中執行以下源代碼就會死鎖。

dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{NSLog(@"Hello")});

也就是說,dispatch_sync函數在等待block塊代碼執行完畢才能執行,而block塊的執行在主線程中,所以dispatch_sync在主線程中調用的話就會發生死鎖。

發生死鎖有如下解釋:

在這里只考慮Serial Dispatch Queue,比如Main Thread Queue;而Concurrent Dispatch Queue一般情況不會發生,暫時沒有研究。dispatch_sync(queue1, block);假設該語句在queue0中執行,則會阻塞(等待)queue0直到queue1中的block執行結束。當queue0和queue1不同時,queue0與queue1為并行執行,此時queue0等待,queue1執行block,queue0與queue1互不影響,直到queue1的block執行結束,queue0阻塞也結束,即dispatch_sync語句返回。當queue0和queue1相同(且為串行隊列Serial Dispatch Queue)時,即dispatch_sync與block在同一個隊列中,此時queue0已經阻塞,不可能再執行block,更無法等待block執行結束,因此造成死鎖。

官方文檔指出:dispatch_sync的當前執行隊列與提交block執行的目標隊列相同時將造成死鎖。
Submits a block to a dispatch queue for synchronous execution. Unlike dispatch_async, this function does not return until the block has finished. Calling this function and targeting the current queue results in deadlock.

dispatch_sync runs a block on a given queue and waits for it to complete. In this case, the queue is the main dispatch queue. The main queue runs all its operations on the main thread, in FIFO (first-in-first-out) order. That means that whenever you call dispatch_sync, your new block will be put at the end of the line, and won't run until everything else before it in the queue is done.

The problem here is that the block you just enqueued is at the end of the line waiting to run on the main thread, but your testSample method is currently running on the main thread. The block at the end of the queue can't get access to the main thread until the current method finishes using the main thread

========================================

[深入理解dispatch_sync]

dispatch_sync使用說明
關于dispatch_sync代碼的執行邏輯,恐怕很多人都已經知道了。以如下代碼為例:
NSLog(@"step1");
dispatch_sync(aDispatchQueue, ^{
NSLog(@"step2");
//block具體代碼
});
NSLog(@"step3");

簡而言之,dispatch_sync()中的block會被同步派發,其上下文會被阻塞,直到dispatch_block派發的block被執行完成,這段代碼的執行結果一定是:
step1
step2
step3

但問題是,dispatch_sync()的block的執行線程和dispatch_sync上下文所對應的線程是一個線程嗎?

所派發的block的執行線程和dispatch_sync上下文線程是同一個線程(無論上述代碼中的aDispatchQueue是serial dispatch queue還是concurrent dispatch queue)。

dispatch_sync使用注意事項

Important: You should never call the dispatch_sync or dispatch_sync_f function from a task that is executing in the same queue that you are planning to pass to the function. This is particularly important for serial queues, which are guaranteed to deadlock, but should also be avoided for concurrent queues.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容