最近看了点libdispatch的源码,关于GCD中几个队列的一些代码分析,拿出来共享一下。
之前有人分析过了,GCD提供很多超越传统多线程编程的优势:
-
易用: GCD比之thread跟简单易用。由于GCD基于work unit而非像thread那样基于运算,所以GCD可以控制诸如等待任务结束、监视文件描述符、周期执行代码以及工作挂起等任务。基于block的血统导致它能极为简单得在不同代码作用域之间传递上下文。
-
效率: GCD被实现得如此轻量和优雅,使得它在很多地方比之专门创建消耗资源的线程更实用且快速。这关系到易用性:导致GCD易用的原因有一部分在于你可以不用担心太多的效率问题而仅仅使用它就行了。
-
性能: GCD自动根据系统负载来增减线程数量,这就减少了上下午切换以及增加了计算效率。
没有那么多知识储备按套路说出其中的奥妙之处,直入主题。
-
The main queue: 与主线程功能相同。实际上,提交至main queue的任务会在主线程中执行。main queue可以调用dispatch_get_main_queue()来获得。因为main queue是与主线程相关的,所以这是一个串行队列。
-
Global queues: 全局队列是并发队列,并由整个进程共享。进程中存在三个全局队列:高、中(默认)、低三个优先级队列。可以调用dispatch_get_global_queue函数传入优先级来访问队列。
-
用户队列: 用户队列 (GCD并不这样称呼这种队列, 但是没有一个特定的名字来形容这种队列,所以我们称其为用户队列) 是用函数 dispatch_queue_create 创建的队列. 这些队列是串行的。正因为如此,它们可以用来完成同步机制, 有点像传统线程中的mutex。
MainQueue通常是与主线程相关的,如果放在手机系统中,则应该是与UI线程相关的,因此如果需要移植GCD这一套到你的手机系统(比如android,那么这个mainQueue就不能用Libdispatch原来的代码,而应该通过sdk,将mianqueue关联到UI线程,后话)
GlobalQueue 这是一个全局的, libdispatch定义了6个队列:
dispatch_queue_s dispatch_root_queue[] = {
……
//初始化6个不同的队列;
}
三个commit,三个global队列。分别按高中低三个优先级(目前我看到代码中,这三个队列的优先级视乎没有用到,通常一视同仁)
看看queue的结构;
C中用到的extented union
结构的一些说明:
1. queue_Vtable: 虚拟表,指示处理queue的一些借口,比如probe,invoke等;
2. queue_context: 上下文,关于线程池相关的;
3. semaphore: 信号,线程的挂起和唤醒等;
4. do_targetq: 目标队列,通常非global queue,如mgr_queue,需要压入到glablalQueue中来处理,因此需要指明target_queue
5. do_suspend_cnt: 通常用于指示延时处理的任务,当计数大于等于2表示为延时任务;
6. 其他基本都是一些头尾,计数的信息。
下一篇,将进入分析queue的几个常用接口的处理原理和流程。