GCD源码核心概念

2019/1/1 posted in  iOS基础概念
  • dispatch_queue
    c8319b785fd73afa2150a3710190f3cd
    从这张图中能看出,我们创建的dispatch_queue_t实际上是统一由GCD Thread Pool来进行统一管理。他会根据多线程队列设置的Priority,来统一管理执行的优先级。

  • dispatch_async
    dispatch_async的流程是用链表保存所有提交的block,然后在底层线程池中,依次取出block并执行;而向主队列提交block则会向主线程的Runloop发送消息并唤醒Runloop,接着会在回调函数中取出block并执行。主线程,专门有个存储queue里需要执行的代码段。当执行到主线程的一个循环玩了后,会从这些队列里拿任务一个一个去执行。

当我们调用 dispatch_async(dispatch_get_main_queue(), block) 时,libDispatch 向主线程的 RunLoop 发送消息,RunLoop会被唤醒,并从消息中取得这个 block,并在回调__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__() 里执行这个 block

  • dispatch_sync

理解dispathch_sync 在执行的时候,会阻塞 上下文 任务的执行.

造成死锁的情况
在主线程里执行dispatch_sync(dispatch_main_queue,block);即,上下文环境是主线程,要将任务放到主线程里执行,而且是同步的。dispatch_sync会阻塞当前主线程,又要在主线程里执行block,所以会造成死锁。造成死锁的原因是“当前执行的上下文环境”与“即将要执行的任务也是这个环境"且是同步执行。同步执行不会开启新的线程,会在当前线程里执行。(所以同步执行将任务放到哪种队列没有关系,任务会在当前线程执行)哈哈哈。这个三个条件到达时就会死锁。终于弄懂了。

同步,异步的概念始终与当前执行代码的上下文线程有关系。同步就是讲当前放到其他队列里的任务拿到当前线程执行,执行完后然后返回,继续执行,执行完后返回,继续执行下面的代码。(也就说可以把加到其他队列里的任务拿到当前上下文的线程里去执行)。

  • dispatch_semaphore

  • dispatch_source
    dispatch_source是BSD系统内核kqueue的包装,kqueue() 生成一个内核事件队列,返回该队列的文件描述符。kqueue是在XNU内核中发生各种事件时,在应用程序编程方执行处理的技术。操作dispatch_source实际上就是,通过操作这个 kqueue,进而对内核事件的处理。(哈哈,这个终于可以解释通了)相当于可以监听内核的事件,然后给一个回调,并将回调的代码在指定的线程里面执行。

    特别说明:
    这里的dispatch_source与runloop里的source还是有区别的。dispatch_source是 内核事件,runloop的source是端口事件(线程通信的方式),timer事件源(runloop的Timer依赖于线程的runloop)。

重要理解
dispatch_asyn与dispatch_syn,dispatch_queue,任务队列是任务列,只管装任务。至于是在当前上下文线程,还是开启新的线程执行,是由同步还是异步决定的。同步不用新的线程执行,异步有创建新线程的权利。