是的,專用的串行隊列是一種很好的方式來同步訪問多個線程之間共享的資源。而且,對於串行隊列,每個任務都將等待前一個任務完成。
兩個意見:
雖然這聽起來非常低效的過程,這是隱含在任何同步技術的心臟(基於隊列的或鎖爲基礎的方法是否),其目標是最小化併發共享資源的更新。
但是在很多情況下,串行隊列技術可以比其他常用技術(例如簡單互斥鎖,NSLock
或@synchronized
指令)產生明顯更好的性能。有關其他同步技術的討論,請參閱「線程編程指南」的Synchronization部分。有關使用隊列來代替鎖的討論,請參閱並行編程指南中的從線程部分移除Eliminating Lock-Based Code。
串行隊列模式的變化是使用了「讀寫器」的模式,在那裏你創建一個GCD併發隊列:
queue = dispatch_queue_create("identifier", DISPATCH_QUEUE_CONCURRENT);
然後進行讀取使用dispatch_sync
,但在執行寫入使用dispatch_barrier_async
。淨效率是允許併發讀取操作,但確保寫入不會同時執行。
如果您的資源允許併發讀取,那麼讀寫器模式可以提供比串行隊列更高的性能增益。
因此,簡而言之,而它似乎效率不高有任務#24等待任務#23,這是在你努力減少共享資源的併發更新任何同步技術所固有的。 GCD串行隊列是一個令人驚訝的高效機制,通常比許多簡單的鎖定機制更好。在某些情況下,讀寫器模式可以進一步提高性能。
我原來的答案,下面,是爲了響應原來的問題這混淆了題爲「如何做一個串行調度隊列保證併發?」回想起來,這只是一個意外的錯誤用法。
這是一個有趣的選擇,「串行調度隊列如何保證併發性?」
還有three types of queues,串口,併發和主隊列。顧名思義,串行隊列將不會啓動下一個調度塊,直到前一個完成。 (使用你的例子,這意味着如果任務23需要很長時間,它將不會開始任務24,直到它完成。)有時這是關鍵的(例如,如果任務24取決於任務23的結果或者如果任務23和24個試圖訪問相同的共享資源)。
如果你想這些不同的派遣任務,相對於同時運行到對方,您可以使用併發隊列(無論您通過dispatch_get_global_queue
得到全局併發隊列中的一個,也可以創建使用dispatch_queue_create
用自己的併發隊列DISPATCH_QUEUE_CONCURRENT
選項)。在併發隊列中,許多分派的任務可能會同時運行。使用併發隊列需要注意一些問題(特別是共享資源的synchronization),但在正確實施時可以產生顯着的性能優勢。
作爲這兩種方法之間的折中方案,您可以使用操作隊列,它可以是併發的,但也可以通過設置maxConcurrentOperationCount
來限制隊列中有多少操作將同時運行。您將使用這種典型場景是在執行後臺網絡任務時,您不需要超過五個併發網絡請求。
欲瞭解更多信息,請參閱Concurrency Programming Guide。
來源
2013-09-25 17:13:33
Rob
看完這個問題後,標題應該是:串行調度隊列是否保證串行執行?答案是肯定的,因爲串行執行是隊列的屬性,而不是dispatch_ [async | sync]函數的屬性。 – Jano
Jano謝謝。我將調度異步與隊列屬性混爲一談,這是兩個不同的想法。對原始標題中的愚蠢單詞選擇抱歉。我已經修復了標題 – user798719