GCD整理

基本的數據結構

GCD的類都是struct定義的。

  • 包括所有的父類的數據成員,都平鋪重復的寫在一個個的struct中。
  • 提高效率,避免引入繼承機制帶來的代碼執(zhí)行上的延遲.
  • 為了減少代碼量和易讀性,做了許多宏定義。

dispatch_object_t
GCD中類都繼承自統一的基類dispatch_object_t。是一個聯合union,作用和基類指針相似,所有的子類型都可以用dispatch_object_t統一表示。

_os_object_s
表示系統對象的基類_os_object_s。

dispatch_continuation_s
向queue提交的任務,無論block還是function形式,最終都會被封裝為dispatch_continuation_s。
保存block的上下文環(huán)境和block執(zhí)行函數等。

dispatch_queue_s
GCD中的queue。

dispatch_queue_attr_s
GCD中的隊列的屬性與狀態(tài)。

GCD線程概況

在GCD中一共有2個線程池管理著任務,一個是主線程池,另一個就是除了主線程任務的線程池。主線程池由序號1的隊列管理,其他有序號2的隊列進行管理。加上runloop運行的runloop隊列,一共就有16個隊列。

1號 main queue,2號 manager queue,3沒有使用,4到11表示global queue,再往后就是用戶自定義queue了。

application啟動的時候就會初始化這些root隊列的_dispatch_root_queues_init函數。

GCD用到的queue,無論是自己創(chuàng)建的,或是獲取系統的main queue還是global queue,其最終都是落腳于GCD root queue中??梢栽诖a中的任意位置創(chuàng)建queue,但最終GCD管理的,就這(4到15)12個root queue,分別有不同的優(yōu)先級和序列號。這種思路有點類似于命令模式,即分散創(chuàng)建,集中管理。

dispatch_queue_create
用戶要創(chuàng)建一個queue的時候,需要指定target queue,即創(chuàng)建的queue最終是在哪個queue上執(zhí)行的,這個target queue會取root queue之一。

調用dispatch_queue_create,GCD內部會調用_dispatch_queue_create_with_target, 它首先會根據我們創(chuàng)建的queue的屬性:DISPATCH_QUEUE_SERIALDISPATCH_QUEUE_CONCURRENT,到root queue數組中取出一個對應的queue作為target queue。然后,會新建一個dispatch_queue_t對象,并設置其target queue,返回給用戶。同時,在GCD內部,新建的queue還會被加入introspection queue列表中

dispatch_get_global_queue
首先將外部傳入的queue優(yōu)先級轉換為GCD內部的優(yōu)先級dispatch_qos_t qos。 然后,在調用_dispatch_get_root_queue 獲取root queue中對應的queue。

dispatch_get_main_queue
main queue是由系統在main()方法調用前創(chuàng)建的。專門綁定到main thread上。而且,為了觸發(fā)提交到main queue上的block,和其他queue不一樣,main queue上的任務是依賴于main runloop觸發(fā)的。

application啟動的時候就會初始化這些root隊列的_dispatch_root_queues_init函數。

dispatch_sync
dispatch_sync直接調用的是dispatch_sync_f

裝入到自定義的任務和方法都被封裝成 dispatch_continuation_t 結構體后,扔到其掛靠的root隊列里去,所以自己創(chuàng)建的隊列只是一個代理人身份,真正的管理人是其對應的root隊列。
最后通過_dispatch_continuation_pop方法把事件壓入隊列執(zhí)行
_dispatch_sync_wait 檢測死鎖的函數

dispatch_async
無論“線程標示”是什么類型的queue,GCD首先會將傳入隊列和方法打包成dispatch_continuation_t類型,然后調用方法_dispatch_continuation_async。

dispatch_async底層運用了線程池,會在和當前線程不同的線程上處理任務。

串行任務
將block打包成dispatch_continuation_t, 然后把dispatch_queue_t通過_dispatch_continuation_push入隊到響應的root queue中,root queue中的線程池中的線程會被喚醒,執(zhí)行線程函數_dispatch_worker_thread3,root queue會被傾倒,執(zhí)行queue中的任務。

并行任務
將block打包成dispatch_continuation_t,然后并行隊列會走 _dispatch_async_f2
首先會被替換為對應的root queue,將自定義dispatch_queue_t入隊。如果是第一次入隊,則會去激活所有的root queue,即創(chuàng)建XUN 內核支持的workqueue(升級版線程池,會自動判斷是否需要創(chuàng)建新的線程),然后將workqueue的工作函數設置為_dispatch_worker_thread3。_dispatch_worker_thread3 會調用_dispatch_root_queue_drain,將root queue進行清空,它會清空所有提交到當前root queue中的dispatch_queue_t,并執(zhí)行它們的dq任務。

dispatch_once
#define dispatch_once _dispatch_once 是一個宏定義
當單例方法執(zhí)行完畢,GCD會將onceToken置為~0。如果再次調用單例方法,GCD會發(fā)現onceToken已經使用過,就直接返回了,并且用原子操作防止多線程下多次調用。

dispatch_group
dispatch_group的相關函數是通過dispatch_semaphore控制的

dispatch_group_create
創(chuàng)建一個dispatch_group_t類型實例并返回。實際是創(chuàng)建了一個信號量 通過_dispatch_semaphore_class_init控制的

dispatch_group_wait
內部是調用的_dispatch_group_wait_slow

dispatch_semaphore_create
調用_dispatch_semaphore_class_init

dispatch_semaphore_wait
調用_dispatch_group_wait_slow

dispatch_barrier_async
dispatch_async直接把任務扔到root隊列,而dispatch_barrier_async是把任務在到自定義的隊列。

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容