dispatch_sync
做兩兩件事:
- 隊列塊
- 塊當前線程,直到該塊已經完成運行
鑑於主線程是一個串行隊列(這意味着它只使用一個線程),以下語句:
dispatch_sync(dispatch_get_main_queue(), ^(){/*...*/});
將導致以下事件:
dispatch_sync
隊列在主隊列塊。
dispatch_sync
阻塞主隊列的線程,直到塊完成執行。
dispatch_sync
永遠等待,因爲塊應該運行的線程被阻塞。
理解這一點的關鍵是dispatch_sync
不執行塊,它只是排隊它們。執行將在運行循環的未來迭代中發生。
以下方法:
if (queueA == dispatch_get_current_queue()){
block();
} else {
dispatch_sync(queueA,block);
}
是完全沒有問題的,但要知道,它不會保護你免受涉及隊列的層次結構複雜的場景。在這種情況下,當前隊列可能與您嘗試發送塊的先前阻止的隊列不同。例如:在調度隊列
dispatch_sync(queueA, ^{
dispatch_sync(queueB, ^{
// dispatch_get_current_queue() is B, but A is blocked,
// so a dispatch_sync(A,b) will deadlock.
dispatch_sync(queueA, ^{
// some task
});
});
});
對於複雜的情況下,讀/寫密鑰值數據:
dispatch_queue_t workerQ = dispatch_queue_create("com.meh.sometask", NULL);
dispatch_queue_t funnelQ = dispatch_queue_create("com.meh.funnel", NULL);
dispatch_set_target_queue(workerQ,funnelQ);
static int kKey;
// saves string "funnel" in funnelQ
CFStringRef tag = CFSTR("funnel");
dispatch_queue_set_specific(funnelQ,
&kKey,
(void*)tag,
(dispatch_function_t)CFRelease);
dispatch_sync(workerQ, ^{
// is funnelQ in the hierarchy of workerQ?
CFStringRef tag = dispatch_get_specific(&kKey);
if (tag){
dispatch_sync(funnelQ, ^{
// some task
});
} else {
// some task
}
});
說明:
- 我創建一個
workerQ
隊列指向一個funnelQ
隊列。在真實代碼中,如果您有多個「工作」隊列並且想要一次恢復/暫停(通過恢復/更新其目標隊列)來實現這一功能很有用。
- 我可能會在任何時候漏斗我的工人隊列,所以要知道他們是否漏斗,我標記
funnelQ
「漏斗」一詞。
- 在路上我
dispatch_sync
東西到workerQ
,無論出於什麼原因我想dispatch_sync
到funnelQ
,但避免dispatch_sync到當前隊列,所以我檢查標籤,並採取相應的行動。因爲get逐步走向層次結構,所以在workerQ
中找不到該值,但會在funnelQ
中找到該值。這是查找層次結構中是否有任何隊列是我們存儲值的方法。因此,阻止dispatch_sync到當前隊列。
如果你想知道關於讀/寫上下文數據的功能,主要有三種:
dispatch_queue_set_specific
:寫入隊列。
dispatch_queue_get_specific
:從隊列中讀取。
dispatch_get_specific
:便捷功能從當前隊列中讀取。
該鍵是通過指針進行比較,並且從未解除引用。 setter中的最後一個參數是釋放鍵的析構函數。
如果您想知道「將一個隊列指向另一個隊列」,那就意味着這一點。例如,我可以將隊列A指向主隊列,並且它會導致隊列A中的所有塊在主隊列中運行(通常這是爲UI更新完成的)。
'dispatch_get_current_queue()'由現在已經過時。去檢測主隊列的方式是'NSThread.isMainThread()'(SWIFT)或[NSThread isMainThread](目標C) – udondan
'NSThread.isMainThread()'是不可靠的,因爲在極少數情況下在主隊列塊, GCD重用主線程來執行其他隊列。參見[1](http://blog.krzyzanowskim.com/2016/06/03/queues-are-not-bound-to-any-specific-thread/),[2](http://blog.benjamin -encz.de/post/main-queue-vs-main-thread/)。 – Jano
@jtbandes在將問題標爲重複項時請注意。這個問題顯然比你所聯繫的問題更老,活動也更多,也許他們應該朝相反的方向關閉。 –