zoukankan      html  css  js  c++  java
  • 多线程GCD源码分析(三)

    1. 之前栈栏函数在使用AFNetwork会出现问题。原因是AFN有一个自己的队列 ”com.almofire.cn.session“, 所以在使用的时候并不知道AFN底层有一个队列,就会出现栈栏函数失效没有达到之前顺序执行的预期。

    libdispatch源码:https://opensource.apple.com/tarballs/libdispatch/  github:https://github.com/apple

    首先查看队列是如何产生的:dispatch_queue_create(创建队列)

    dispatch_queue_create("com.cooci.cn", NULL);

     

     

    dispatch_queue_attr_info_t

    _dispatch_queue_attr_to_info(dispatch_queue_attr_t dqa)

    {

    dispatch_queue_attr_info_t dqai = { };

     

    if (!dqa) return dqai;

     

    #if DISPATCH_VARIANT_STATIC

    if (dqa == &_dispatch_queue_attr_concurrent) {

    dqai.dqai_concurrent = true;

    return dqai;

    }

    #endif

     

    if (dqa < _dispatch_queue_attrs ||

    dqa >= &_dispatch_queue_attrs[DISPATCH_QUEUE_ATTR_COUNT]) {

    DISPATCH_CLIENT_CRASH(dqa->do_vtable, "Invalid queue attribute");

    }

     

    // 苹果的算法

    size_t idx = (size_t)(dqa - _dispatch_queue_attrs);

     

    // 位域

    // 0000 000000000 00000000000 0000 000  1

     

    dqai.dqai_inactive = (idx % DISPATCH_QUEUE_ATTR_INACTIVE_COUNT);

    idx /= DISPATCH_QUEUE_ATTR_INACTIVE_COUNT;

     

    dqai.dqai_concurrent = !(idx % DISPATCH_QUEUE_ATTR_CONCURRENCY_COUNT);

    idx /= DISPATCH_QUEUE_ATTR_CONCURRENCY_COUNT;

     

    dqai.dqai_relpri = -(idx % DISPATCH_QUEUE_ATTR_PRIO_COUNT);

    idx /= DISPATCH_QUEUE_ATTR_PRIO_COUNT;

     

    dqai.dqai_qos = idx % DISPATCH_QUEUE_ATTR_QOS_COUNT;

    idx /= DISPATCH_QUEUE_ATTR_QOS_COUNT;

     

    dqai.dqai_autorelease_frequency =

    idx % DISPATCH_QUEUE_ATTR_AUTORELEASE_FREQUENCY_COUNT;

    idx /= DISPATCH_QUEUE_ATTR_AUTORELEASE_FREQUENCY_COUNT;

     

    dqai.dqai_overcommit = idx % DISPATCH_QUEUE_ATTR_OVERCOMMIT_COUNT;

    idx /= DISPATCH_QUEUE_ATTR_OVERCOMMIT_COUNT;

     

    return dqai;

    }

    串行和并行的区分

     

    _dispatch_queue_init(dq, dqf, dqai.dqai_concurrent ?

    DISPATCH_QUEUE_WIDTH_MAX : 1, DISPATCH_QUEUE_ROLE_INNER |

    (dqai.dqai_inactive ? DISPATCH_QUEUE_INACTIVE : 0));

    初始化队列对象,如果是并发传最大DISPATCH_QUEUE_WIDTH_MAX,如果是串行队列传1

     类似于NSObject

     

     

    并发队列口子大,串行队列只能1个

     

     

     _dispatch_root_queues[] 是一个系统初始化的静态数组,装了很多queue --target queue,这个也解释了全局是因为并发队列是放在静态数组里面的。

     

     自己创建的并发和全局并发的width不一样自己的是0xffe,全局的是0xfff

    dispatch_get_global_queue是直接用_dispatch_get_root_queue方法 从 rootqueue里面去的

     主队列的获取:

    dispatch_get_main_queue

    主队列静态数组:

     

        // dispatch_queue_main_t 串行队列

        // DISPATCH_DECL_SUBCLASS(dispatch_queue_main, dispatch_queue_serial

        // 重写,所以是串行队列

    同步异步函数:

    dispatch_sync(dis

    _dispatch_sync_f(dis

    _dispatch_sync_f_inline

     

     

     

     

     

    死锁原因:调度3去执行,但是程序还在等待3。要被调度线程id的和被锁的等待执行完成的线程id是同一个就会发生死锁crash。

    异步并发:

    直接往工作队列中添加线程,并发就是在这里创建线程

     

     这段代码是判断线程池容积,如果要创建的线程数大于可以创建的线程数,就会崩溃

     并发队列pthread_creat其实就是普通的创建并发队列,利用do-while一直创建线程,知道--remaining

    异步执行线程的block

    执行block内容:

     

     单例:

     dispatch_once_t  是long类型的

     

    val就是我们传进来的once_token,单例的意思是如果来过一次,下次就不过来,直接return。

     

    如果执行过mark_done(1)

    标记为DLOCK_ONCE_DONE

     

    信号量 :

    //    相当于-1

        dispatch_wait(sem, DISPATCH_TIME_FOREVER);

     

     

    调度组:

    dispatch_group_create创建

     

    dispatch_group_enter进组相当于-1

    出组相当于+1

     

     

  • 相关阅读:
    docker harbor 修改密码 重置密码 sql
    mongodb监控并在服务挂掉后自动重启脚本
    centos7 ffmpeg安装 rtsp相关
    vscode vue 自动格式化代码
    开启go module
    Python3.x:打包为exe执行文件(window系统)
    Docker 日志都在哪里?怎么收集?
    HttpsURLConnection信任任何证书
    SP3734 PERIODNI
    联赛前的记录
  • 原文地址:https://www.cnblogs.com/coolcold/p/12203391.html
Copyright © 2011-2022 走看看