Dispatch Queue编程
Dispatch Queue 对于咱们开发者来讲应该是很是熟悉了,运用的场景很是之多,可是他的内部是如何实现的呢?多线程
不难想象,GCD的实现须要使用以上这些工具,可是若是仅用这些内容即可实现,那么就不须要内核级实现了。(实际上在通常的Linux内核中可能使用面向Linux操做系统而移植的GCD)。并发
甚至有人会想,只要努力编写线程管理的代码,就根本用不到GCD,是这样的吗?框架
咱们先来回顾一下苹果的官方说明:async
一般,应用程序中编写的线程管理用的代码要在系统级实现。函数
实际上正如这句话所说,在系统级即iOS和OS X的核心XNU内核级上实现,所以不管编程人员如何努力编写管理线程的代码,在性能方面也不可能赛过XNU内核级所实现的GCD。工具
使用GCD要比使用pthreads和NSThread这些通常的多线程编程API更好。而且,若是用GCD就没必要编写为操做线程反复出现的相似的源代码(这里被称为固定源代码片断),而能够在线程中集中实现处理内容,真的是好处多多。咱们尽可能多使用GCD或者使用了Cocoa框架GCD的NSOperationQueue类等API。oop
那么首先确认一下用于实现Dispatch Queue 而使用的软件组件。如表所示:性能
编程人员所使用GCD的API所有包含在libdispatch库的C语言函数。Dispatch Queue经过结构体和链表,被实现为FIFO队列。FIFO队列主要是负责管理经过dispatch_async等函数所追加的一系列Blocks。因此咱们能够理解为一旦咱们在程序中由上到下追加了一组Blocks,那么排除掉dispatch_after,其内部的追加过程是一个先进先出原则。spa
可是Block自己并非直接加入到这个FIFO队列中,而是先加入Dispatch Continuation这一dispatch_continuation_t类型结构体中,而后再进入FIFO队列。该结构体用于记忆Block所属的Dispatch Group和其余一些信息,至关于通常常说的执行上下文(execution context)。
Dispatch Queue可经过dipatch_set_target_queue函数设定,能够设定执行该Dispatch Queue处理的Dispatch Queue为目标。该目标可像串珠子同样,设定多个链接在一块儿的Dispatch Queue,可是在链接串的最后必须设定为Main Dispatch Queue,或各类优先级的Global Dispatch Queue,或是准备用于Serial Dispatch Queue的各类优先级的Global Dispatch Queue。
Main Dispatch Queue 在RunLoop中执行Block。这并非使人耳目一新的新技术。
Global Dispatch Queue有以下8种:
Global Dispatch Queue (High priority)
Global Dispatch Queue (Default priority)
Global Dispatch Queue (Low priority)
Global Dispatch Queue (Background priority)
Global Dispatch Queue (High overcommit priority)
Global Dispatch Queue (Default overcommit priority)
Global Dispatch Queue (Low overcommit priority)
Global Dispatch Queue (Background overcommit priority)
注意前面四种 和后面四种不一样优先级的Queue有一词之差:Overcommit。其区别就在于Overcommit Queue无论系统状态如何都会强制生成线程队列。
这8种Global Dispatch Queue 各使用一个pthread_workqueue。GCD初始化时,使用pthread_workqueue_create_np函数生成pthread_wrokqueue。
pthread_wrokqueue包含在Libc提供的pthreads API中。它经过系统的bsdthread_register和workq_open函数调用,在初始化XNU内核的workqueue以后获取其信息。
XNU内核有4种workqueue:
WORKQUEUE_HIGH_PRIOQUEUE
WORKQUEUE_DEFAULT_PRIOQUEUE
WORKQUEUE_LOW_PRIOQUEUE
WORKQUEUE_BG_PRIOQUEUE
以上为4种执行优先级的workqueue。该执行优先级与Global Dispatch Queue的4种执行优先级相同。
下面看一下Dispatch Queue中执行Block的过程。当在Global Dispatch Queue 中执行Block时,libdispatch 从Global Dispatch Queue自身的FIFO队列取出Dispatch Continuation,调用pthread_workqueue_additem_np函数。将该Global Dispatch Queue 自己、符合其优先级的workqueue信息以及执行Dispatch Continuation的回调函数等传递给参数。
pthread_workqueue_additem_np函数使用workq_kernreturn系统调用,通知workqueue增长应当执行的项目。根据该通知,XNU内核基于系统状态判断是否要生成线程。若是是Overcommit优先级的Global Dispatch Queue ,workqueue则始终生成线程。
该线程虽然与iOS和OS X中一般使用的线程大体相同,可是有一部分pthread API不能使用。详细信息能够参考苹果的官方文档《并发编程指南》的“Compatibility with POSIX Threads“这一章节。
另外,由于workqueue生成的线程在实现用于workqueue的线程计划表中运行,他的上下文切换(shift context)与普通的线程有很大的不一样。这也是咱们使用GCD的缘由。
workqueue的线程执行pthread_workqueue函数,该函数调用libdispatch的回调函数。在该回调函数中执行加入到Global Dispatch Queue中的下一个Block。
以上就是Dispatch Queue执行的大概过程。
由此可知,在编程人员本身编写的线程管理代码中想发挥出原生GCD的性能是不可能的。
原文连接:http://blog.csdn.net/mobanchengshuang/article/details/10839049