GCD整理

基本的数据结构

GCD的类都是struct定义的。

  • 包括所有的父类的数据成员,都平铺重复的写在一个个的struct中。
  • 提高效率,避免引入继承机制带来的代码执行上的延迟.
  • 为了减少代码量和易读性,做了许多宏定义。

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的上下文环境和block执行函数等。

dispatch_queue_s
GCD中的queue。

dispatch_queue_attr_s
GCD中的队列的属性与状态。

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,无论是自己创建的,或是获取系统的main queue还是global queue,其最终都是落脚于GCD root queue中。可以在代码中的任意位置创建queue,但最终GCD管理的,就这(4到15)12个root queue,分别有不同的优先级和序列号。这种思路有点类似于命令模式,即分散创建,集中管理。

dispatch_queue_create
用户要创建一个queue的时候,需要指定target queue,即创建的queue最终是在哪个queue上执行的,这个target queue会取root queue之一。

调用dispatch_queue_create,GCD内部会调用_dispatch_queue_create_with_target, 它首先会根据我们创建的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优先级转换为GCD内部的优先级dispatch_qos_t qos。 然后,在调用_dispatch_get_root_queue 获取root queue中对应的queue。

dispatch_get_main_queue
main queue是由系统在main()方法调用前创建的。专门绑定到main thread上。而且,为了触发提交到main queue上的block,和其他queue不一样,main queue上的任务是依赖于main runloop触发的

application启动的时候就会初始化这些root队列的_dispatch_root_queues_init函数。

dispatch_sync
dispatch_sync直接调用的是dispatch_sync_f

装入到自定义的任务和方法都被封装成 dispatch_continuation_t 结构体后,扔到其挂靠的root队列里去,所以自己创建的队列只是一个代理人身份,真正的管理人是其对应的root队列。
最后通过_dispatch_continuation_pop方法把事件压入队列执行
_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中的线程池中的线程会被唤醒,执行线程函数_dispatch_worker_thread3,root queue会被倾倒,执行queue中的任务。

并行任务
将block打包成dispatch_continuation_t,然后并行队列会走 _dispatch_async_f2
首先会被替换为对应的root queue,将自定义dispatch_queue_t入队。如果是第一次入队,则会去激活所有的root queue,即创建XUN 内核支持的workqueue(升级版线程池,会自动判断是否需要创建新的线程),然后将workqueue的工作函数设置为_dispatch_worker_thread3。_dispatch_worker_thread3 会调用_dispatch_root_queue_drain,将root queue进行清空,它会清空所有提交到当前root queue中的dispatch_queue_t,并执行它们的dq任务。

dispatch_once
#define dispatch_once _dispatch_once 是一个宏定义
当单例方法执行完毕,GCD会将onceToken置为~0。如果再次调用单例方法,GCD会发现onceToken已经使用过,就直接返回了,并且用原子操作防止多线程下多次调用。

dispatch_group
dispatch_group的相关函数是通过dispatch_semaphore控制的

dispatch_group_create
创建一个dispatch_group_t类型实例并返回。实际是创建了一个信号量 通过_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是把任务在到自定义的队列。

你可能感兴趣的:(GCD整理)