GCD的一些分析-2

将Queue中的api归类为:

同步sync:disptach_sync_f

异步async;disptach_async_f

异步延时asyncDelayed: 暂且叫disptach_cannel

取消延时disptach_source_cancel。


先看看一张队列调用的关系图:

这张图表明了GCD中队列的并发关系,除了globalqueue之外,其他的queue,都会在globalQueue中调度,调度之后再按照queue自身的结构调度。


1. sync

     GlobalQueue和Private Queue(前面称为用户队列). 正对sync都是直接执行,封装的block没有直接压队,这部分应该是根据开发者自行的需要可以修改的。

2. Async

    先从GlobalQueue入手;既然是异步的操作,就会存在多任务和多线程的问题,多任务主要看GCD如何维护这些任务;

    GCD之所以用到这些队列,可以简单的认为是一种内存共享的方式,也就是先将任务放入队列, 通过一些规则管理起来,然后再创建线程,从队列中取出这些任务,然后执行。

上图则是任务的结构;

任务创建之后,需要将任务插入到队列,其流程图如下:


进入到probe阶段_dispatch_queue_wakeup_globel中后,获取dq的上下文c_txt;然后调用dispatch_smaphore_signal(c_txt->dgq_thread_mediator)。将信号值加1(原子操作),如果信号值大于0,表示当前资源可用,可以进行继续往下进行;否则表示有正在sleep的线程在等待唤醒,那么直接唤醒sleep的线程处理即可。


当semaphore_signal之后返回0,表示有可用资源,那么更新线程池的size(原子操作减1)。接下来创建工作线程_dispatch_work_thread。

创建子线程之后,进入到_dispatch_worker_thread中,先设置线程中信号掩码。执行_dispatch_worker_thread2。该函数用于真正执行任务。_dispatch_worker_thread2会循环的通过_dispatch_queue_concurrent_drain_one从dq中取出任务item。然后交给_dispatch_continuation_pop来执行。

_dispatch_queue_concurrent_drain_one的流程如下图。当获取之后返回Head,交给_dispatch_continuation_pop,_dispatch_continuation_pop获取到dispatch_continuation_t的dc对象后,通过dc_func(dc_ctxt)执行任务。

_dispatch_worker_thread2执行完后,回到了_dispatch_worker_thread,这时候会进入_dispatch_semaphore_wait(qc->dgq_thread_mediator,1seconds)。及线程会等待1s,看是否有其他资源过来,若发现可用资源为0,那么返回;否则继续执行。

子线程的work完成之后,将线程池大小加1,如果发现dq的tail非空,表示还有任务没有处理,那么重新进入_dispatch_queue_wakeup_global(dq)中。然后返回。
当存在多个任务到达时,可能出现之前semphore_signal时,发现可用信号值为负值,那么表示有线程等待唤醒,这其实是多个子线程在_dispatch_semaphore_wait时引起的。因此只需要唤醒它们就行。


下一篇将分析异步延时处理任务
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值