dispatch_async 函數(shù)的“async”意味著“非同步”(asynchronous),就是將指定的Block“非同步”地追加到指定的Dispatch Queue中。dispatch_async函數(shù)不做任何等待。
既然有“async”,當(dāng)然就有“sync”,即 dispatch_sync函數(shù)。它意味著“同步”(synchronous),也就是將指定的Block" 同步"追加到指定的Dispatch Queue中。在追加Block結(jié)束之前,dispatch_sync 函數(shù)會一直等待。
dispatch_sync函數(shù)簡單,容易引起問題。即死鎖。
例如如果在主線程中執(zhí)行以下源代碼就會死鎖。
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{NSLog(@"Hello")});
也就是說,dispatch_sync函數(shù)在等待block塊代碼執(zhí)行完畢才能執(zhí)行,而block塊的執(zhí)行在主線程中,所以dispatch_sync在主線程中調(diào)用的話就會發(fā)生死鎖。
發(fā)生死鎖有如下解釋:
在這里只考慮Serial Dispatch Queue,比如Main Thread Queue;而Concurrent Dispatch Queue一般情況不會發(fā)生,暫時沒有研究。dispatch_sync(queue1, block);假設(shè)該語句在queue0中執(zhí)行,則會阻塞(等待)queue0直到queue1中的block執(zhí)行結(jié)束。當(dāng)queue0和queue1不同時,queue0與queue1為并行執(zhí)行,此時queue0等待,queue1執(zhí)行block,queue0與queue1互不影響,直到queue1的block執(zhí)行結(jié)束,queue0阻塞也結(jié)束,即dispatch_sync語句返回。當(dāng)queue0和queue1相同(且為串行隊(duì)列Serial Dispatch Queue)時,即dispatch_sync與block在同一個隊(duì)列中,此時queue0已經(jīng)阻塞,不可能再執(zhí)行block,更無法等待block執(zhí)行結(jié)束,因此造成死鎖。
官方文檔指出:dispatch_sync的當(dāng)前執(zhí)行隊(duì)列與提交block執(zhí)行的目標(biāo)隊(duì)列相同時將造成死鎖。
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使用說明
關(guān)于dispatch_sync代碼的執(zhí)行邏輯,恐怕很多人都已經(jīng)知道了。以如下代碼為例:
NSLog(@"step1");
dispatch_sync(aDispatchQueue, ^{
NSLog(@"step2");
//block具體代碼
});
NSLog(@"step3");
簡而言之,dispatch_sync()中的block會被同步派發(fā),其上下文會被阻塞,直到dispatch_block派發(fā)的block被執(zhí)行完成,這段代碼的執(zhí)行結(jié)果一定是:
step1
step2
step3
但問題是,dispatch_sync()的block的執(zhí)行線程和dispatch_sync上下文所對應(yīng)的線程是一個線程嗎?
所派發(fā)的block的執(zhí)行線程和dispatch_sync上下文線程是同一個線程(無論上述代碼中的aDispatchQueue是serial dispatch queue還是concurrent dispatch queue)。
dispatch_sync使用注意事項(xiàng)
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.