GCD整理

作者: Foxhoundsun | 来源:发表于2020-06-09 00:44 被阅读0次

基本的数据结构

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整理

    系统提供的dispatch方法: 为了方便地使用 GCD,苹果提供了一些方法方便我们将 block 放在主线程 或...

  • GCD整理

    这边就整理下GCD一些常用的方式,以及举例子并打印结果说明相应的。一直想去整理然后嘛,要么没时间要么懒...拖到现...

  • GCD整理

    基本的数据结构 GCD的类都是struct定义的。 包括所有的父类的数据成员,都平铺重复的写在一个个的struct...

  • iOS多线程之GCD详解

    原文链接:整理多线程:GCD详解,如有侵权立即删除 一、GCD简介 为什么要用GCD呢? 二、GCD任务和队列 2...

  • 【Objective-C】GCD介绍

    整理自raywenderlich。 1.GCD是嘛? GCD是Grand Central Dispatch的缩写,...

  • GCD整理(一)

    整理一篇关于GCD的文章,自己以后要复习的时候也方便。 GCD(Grand Center Dispatch)异步执...

  • GCD整理(二)

    这篇会整理GCD常用的API 目录1、dispatch_after2、dispatch_apply3、dispat...

  • GCD 简单整理

    GCD (Grand Central Dispatch) 概念 关注两个概念:队列、任务。iOS 多线程方案:pt...

  • 笔记整理:GCD

    一、概述 GCD是用纯C编写,效率很高;其内部自动维护一个线程池,自动管理线程的生命周期;其会利用CPU的多核特性...

  • 多线程之GCD学习整理

    把GCD的资料重新整理了一下 ( ̄. ̄) GCD全称Grand Central Dispatch是Apple开发的...

网友评论

      本文标题:GCD整理

      本文链接:https://www.haomeiwen.com/subject/nmdwzhtx.html