美文网首页iOS
iOS底层探索之多线程(五)—GCD不同队列源码分析

iOS底层探索之多线程(五)—GCD不同队列源码分析

作者: 俊而不逊 | 来源:发表于2021-08-14 14:17 被阅读0次

    回顾

    在上篇博客已经介绍了各种队列和异步、同步函数的组合,GCD的队列和函数,对队列和任务的执行有了清晰的认识, 那么本篇博客将继续介绍GCD的队列和源码分析。

    iOS底层探索之多线程(一)—进程和线程

    iOS底层探索之多线程(二)—线程和锁

    iOS底层探索之多线程(三)—初识GCD

    iOS底层探索之多线程(四)—GCD的队列

    在这里插入图片描述

    1. 主队列分析

    查看主队列的api如下图:

    dispatch_get_main_queue
    • 主队列是一个特殊的串行队列
    • 主队列在调用main()函数之前自动创建的。
    • 主队列在应用程序上下文中用于与主线程和main runloop 交互。

    那么断点在main函数处去验证一下

    验证main_queue

    通过断点,确实验证了主队列是在调用main()函数之前自动创建的。

    那么我们要看底层源码,该怎么看啊,首先我们得知道 GCD是属于哪个源码的,才能进一步去探索分析。

    • 再次通过断点寻找,如下图

      寻找 GCD源码出处
      通过 bt打印堆栈信息,可以定位到libdispatch.dylib动态库,那么就去苹果开源网站去下载源码试试。
    • 下载libdispatch.dylib源码,探索GCD

      libdispatch
    • libdispatch 源码

      GCD源码libdispatch
      libdispatch源码比较难受
    • 注释非常的少

    • 宏定义非常的多

    • 函数名非常的长

    这是一个硬骨头,非常的不好啃,只能硬着头皮慢慢啃了,难受啊!

    • 源码搜索dispatch_get_main_queue
      dispatch_get_main_queue

    dispatch_get_main_queue是通过DISPATCH_GLOBAL_OBJECT返回的,是一个宏定义

    • DISPATCH_GLOBAL_OBJECT
      DISPATCH_GLOBAL_OBJECT宏定义
    • 通过_dispatch_main_q参数搜索
    dispatch_get_main_queue(void)
    {
        return DISPATCH_GLOBAL_OBJECT(dispatch_queue_main_t, _dispatch_main_q);
    }
    
    _dispatch_main_q
    • 还可以通过主队列的dq_label搜索如下:
    在这里插入图片描述
    在源码中有dq_serialnum = 1,这是不是意味着可以作为主队列就是 串行队列的依据呢? 现在还不得而知,那么去看看串行队列底层是怎么实现的,或许可以找到答案!
    • 主队列的初始化是在dispatch_init()方法中?
      在这里插入图片描述
    • dispatch_init()中成功找到了主队列初始化的地方,
    • 获取默认队列,
    • 并将主队列地址绑定到当前队列和主线程中

    2. 串行、并发队列分析

    串行队列并发队列都通过dispatch_queue_create创建的,那么去搜索一下

    dispatch_queue_create
    通过搜索定位到dispatch_queue_create,在通过返回的是_dispatch_lane_create_with_target,再继续搜索
    _dispatch_lane_create_with_target
    • 代码比较长,从返回值看,再推导


      从返回值推导
    • _dispatch_object_alloc申请内存空间
    • _dispatch_queue_init构造函数初始化
    • 判断是否为并发队列,如果是,传入DISPATCH_QUEUE_WIDTH_MAX,否则传入1。也就是说,串行队列这里传入1,如果是并发队列,则传入DISPATCH_QUEUE_WIDTH_MAX
      DISPATCH_QUEUE_WIDTH_MAX
    • dq进行设置,如dq_labeldq_priority

    _dispatch_queue_init

    在这里插入图片描述
    • 把前面的 width 传进来,赋值dqf |= DQF_WIDTH(width)
    • DQF_WIDTH(width),也就是用来确定队列的类型,以此来区分串行队列并发队列
      DISPATCH_QUEUE_SERIAL_NUMBER_INIT
      其他参数vtabledqai,分别是什么呢?继续探索
      在这里插入图片描述
    • dqai初始化

    在开头有这么一句代码

    // dqai 创建 - dqa传入的属性串行还是并行
    dispatch_queue_attr_info_t dqai = _dispatch_queue_attr_to_info(dqa);
    
    
    • _dispatch_queue_attr_to_info

      _dispatch_queue_attr_to_info
      在这里进行初始化了dqai,并判断dqa的类型,如果是并发队列,则设置并发队列true,否则默认为串行队列。在调用_dispatch_queue_initdq进行构造时,对队列类型进行了区分,也就是DQF_WIDTH(width)的传参,串行队列width=1,否则为并发队列
    • vtable

            const void *vtable; // - 设置类 类是通过宏定义拼接而成
            if (dqai.dqai_concurrent) {
                    // OS_dispatch_##name##_class
                    // OS_dispatch_queue_concurrent - 宏定义拼接类类型
                    vtable = DISPATCH_VTABLE(queue_concurrent);
            } else {
                    vtable = DISPATCH_VTABLE(queue_serial);
            }
    
    

    vtable可以理解为是一个类,或者说构造队列的模板类,qai来区分队列的类型,根据队列的类型来初始化不同的vtableDISPATCH_VTABLE是一个宏定义的方法,全局搜索DISPATCH_VTABLE的定义

    // DISPATCH_VTABLE定义
    #define DISPATCH_VTABLE(name) DISPATCH_OBJC_CLASS(name)
    
    // vtable symbols - 模板
    #define DISPATCH_OBJC_CLASS(name) (&DISPATCH_CLASS_SYMBOL(name))
    
    // 拼接形成类
    #define DISPATCH_CLASS_SYMBOL(name) OS_dispatch_##name##_class
    
    

    DISPATCH_VTABLE函数的传参根据不同的队列类型传参不一致。

    并发队列
    queue_concurrent参数,最终拼接后,队列类型对应的类为:OS_dispatch_queue_concurrent

    串行队列
    queue_serial参数,最终拼接后,队列类型对应的类为:OS_dispatch_queue_serial

    所以vtable对应的就是队列的类型。通过拼接完成类的定义,这和我们在应用层使用的队列类型是一致的。

    测试代码

    3. 全局队列分析

    进入dispatch_get_global_queueapi

    dispatch_get_global_queue
    • 创建全局并发队列时可以传参数
    • 根据不同服务质量或者优先等级提供不同的并发队列。

    通过全局队列的标识 在源码里面搜索🔍

    全局队列集合
    • 系统会维护一个全局队列集合
    • 根据不同的服务质量或者优先等级提供不同的全局队列
    • 我们在开发工作中默认使用:dispatch_get_global_queue(0, 0)

    更多内容持续更新

    🌹 喜欢就点个赞吧👍🌹

    🌹 觉得有收获的,可以来一波,收藏+关注,评论 + 转发,以免你下次找不到我😁🌹

    🌹欢迎大家留言交流,批评指正,互相学习😁,提升自我🌹

    相关文章

      网友评论

        本文标题:iOS底层探索之多线程(五)—GCD不同队列源码分析

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