iOS底层原理---GCD底层原理
程序员文章站
2022-07-11 13:51:47
简介...
1.简介
1.什么是GCD?
- 全称是 Grand Central Dispatch
- 纯 C 语言,提供了非常多强大的函数
2.GCD的优势
- GCD 是苹果公司为多核的并行运算提出的解决方案
- GCD 会自动利用更多的CPU内核(比如双核、四核)
- GCD 会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
- 程序员只需要告诉 GCD 想要执行什么任务,不需要编写任何线程管理代码
2.任务与队列
1.任务
- 任务使用 block 封装
- 任务的 block 没有参数也没有返回值
1.同步任务
- 函数:
dispatch_sync
- 必须等待当前语句执行完毕,才会执行下一条语句
- 不会开启线程
- 在当前执行 block 的任务
2.异步任务
- 异步
dispatch_async
- 不用等待当前语句执行完毕,就可以执行下一条语句
- 会开启线程执行 block 的任务
- 异步是多线程的代名词
2.队列
1.串行队列
- 任务顺序执行,one by one;
2.并发队列
- 任务随机执行,不需要等待,CPU调度
3.主队列
- 函数:
dispatch_get_main_queue();
- 特殊的串行队列
- 专门用来在主线程上调度任务的队列
- 不会开启线程
如果当前主线程正在执行任务,那么无论主队列中当前被添加了什么任务,都不会被调度
4.全局队列
- 函数:
dispatch_get_global_queue(0,0);
- 为了方便程序员使用,苹果提供了全局队列
全局队列是一个并发队列
- 在使用多线程开发时,如果对队列没有特殊需求,在执行异步任务时,可以直接使用全局队列
5.队列和任务搭配
- 同步串行队列:不开启新线程,串行执行任务;
- 同步并发队列:不开启新线程,串行执行任务;
- 同步主队列:如果在主线程调用,造成
死锁
;如果在其他线程调用,不开启新线程,串行执行,在主线程串行执行任务; - 异步串行队列:开启新线程,串行执行任务;
- 异步并发队列:开启新线程,并发执行任务;
- 异步主队列:不开启新线程,在主线程串行执行任务
- 死锁:
2.GCD源码分析
首先搞了一份libdispatch的源码!
1.创建队列的代码
dispatch_queue_t queue = dispatch_queue_create("gcd_queue", DISPATCH_QUEUE_SERIAL);
//这里我们按住command ,Jump to Definition跳转到下面:
dispatch_queue_t
dispatch_queue_create(const char *_Nullable label,
dispatch_queue_attr_t _Nullable attr);
//只能看到这里了
-
我们只能去libdispatch源码中去看了!
-
下面是我们源码搜索的过程:
-
搜索dispatch_queue_create
-
搜索_dispatch_lane_create_with_target:
//终于来到了核心代码!!!! //在下面的代码中根据参数dqa获取dqai,下面流程的判断都与dispatch_queue_attr_info_t dqai有关 //那么说明dispatch_queue_attr_t dqa也是我们需要研究的对象 //可以下略过此代码片,先去看一下dqa相关的东西,然后回来看下面代码,能使你更能清晰!!!! static dispatch_queue_t _dispatch_lane_create_with_target(const char *label, dispatch_queue_attr_t dqa, dispatch_queue_t tq, bool legacy) { //决定下面代码的一个临时变量 dispatch_queue_attr_info_t dqai = _dispatch_queue_attr_to_info(dqa); //优先级DISPATCH_QOS_USER_INITIATED 和 DISPATCH_QOS_BACKGROUND dispatch_qos_t qos = dqai.dqai_qos; #if !HAVE_PTHREAD_WORKQUEUE_QOS if (qos == DISPATCH_QOS_USER_INTERACTIVE) { dqai.dqai_qos = qos = DISPATCH_QOS_USER_INITIATED; } if (qos == DISPATCH_QOS_MAINTENANCE) { dqai.dqai_qos = qos = DISPATCH_QOS_BACKGROUND; } #endif // !HAVE_PTHREAD_WORKQUEUE_QOS //星号以内不是我们关心的 //*************************************************************** _dispatch_queue_attr_overcommit_t overcommit = dqai.dqai_overcommit; if (overcommit != _dispatch_queue_attr_overcommit_unspecified && tq) { if (tq->do_targetq) { DISPATCH_CLIENT_CRASH(tq, "Cannot specify both overcommit and " "a non-global target queue"); } } if (tq && dx_type(tq) == DISPATCH_QUEUE_GLOBAL_ROOT_TYPE) { // Handle discrepancies between attr and target queue, attributes win if (overcommit == _dispatch_queue_attr_overcommit_unspecified) { if (tq->dq_priority & DISPATCH_PRIORITY_FLAG_OVERCOMMIT) { overcommit = _dispatch_queue_attr_overcommit_enabled; } else { overcommit = _dispatch_queue_attr_overcommit_disabled; } } if (qos == DISPATCH_QOS_UNSPECIFIED) { qos = _dispatch_priority_qos(tq->dq_priority); } tq = NULL; } else if (tq && !tq->do_targetq) { // target is a pthread or runloop root queue, setting QoS or overcommit // is disallowed if (overcommit != _dispatch_queue_attr_overcommit_unspecified) { DISPATCH_CLIENT_CRASH(tq, "Cannot specify an overcommit attribute " "and use this kind of target queue"); } } else { if (overcommit == _dispatch_queue_attr_overcommit_unspecified) { // Serial queues default to overcommit! overcommit = dqai.dqai_concurrent ? _dispatch_queue_attr_overcommit_disabled : _dispatch_queue_attr_overcommit_enabled; } } //*************************************************************** if (!tq) { // 第一个参数 qos 为 4 //第二个参数 overcommit 并发为0,串行为1 /*_dispatch_get_root_queue(dispatch_qos_t qos, bool overcommit) { if (unlikely(qos < DISPATCH_QOS_MIN || qos > DISPATCH_QOS_MAX)) { DISPATCH_CLIENT_CRASH(qos, "Corrupted priority"); } // 4-1= 3 // 返回值为 2*3+0/1 = 6/7 return &_dispatch_root_queues[2 * (qos - 1) + overcommit]; } _dispatch_root_queues方法定义:从数组中取出下表为6/7的地址 extern struct dispatch_queue_global_s _dispatch_root_queues[]; struct dispatch_queue_global_s _dispatch_root_queues[] = { #define _DISPATCH_ROOT_QUEUE_IDX(n, flags) \ ((flags & DISPATCH_PRIORITY_FLAG_OVERCOMMIT) ? \ DISPATCH_ROOT_QUEUE_IDX_##n##_QOS_OVERCOMMIT : \ DISPATCH_ROOT_QUEUE_IDX_##n##_QOS) #define _DISPATCH_ROOT_QUEUE_ENTRY(n, flags, ...) \ [_DISPATCH_ROOT_QUEUE_IDX(n, flags)] = { \ DISPATCH_GLOBAL_OBJECT_HEADER(queue_global), \ .dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE, \ .do_ctxt = _dispatch_root_queue_ctxt(_DISPATCH_ROOT_QUEUE_IDX(n, flags)), \ .dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL), \ .dq_priority = flags | ((flags & DISPATCH_PRIORITY_FLAG_FALLBACK) ? \ _dispatch_priority_make_fallback(DISPATCH_QOS_##n) : \ _dispatch_priority_make(DISPATCH_QOS_##n, 0)), \ __VA_ARGS__ \ } _DISPATCH_ROOT_QUEUE_ENTRY(MAINTENANCE, 0, .dq_label = "com.apple.root.maintenance-qos", .dq_serialnum = 4, ), _DISPATCH_ROOT_QUEUE_ENTRY(MAINTENANCE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT, .dq_label = "com.apple.root.maintenance-qos.overcommit", .dq_serialnum = 5, ), _DISPATCH_ROOT_QUEUE_ENTRY(BACKGROUND, 0, .dq_label = "com.apple.root.background-qos", .dq_serialnum = 6, ), _DISPATCH_ROOT_QUEUE_ENTRY(BACKGROUND, DISPATCH_PRIORITY_FLAG_OVERCOMMIT, .dq_label = "com.apple.root.background-qos.overcommit", .dq_serialnum = 7, ), _DISPATCH_ROOT_QUEUE_ENTRY(UTILITY, 0, .dq_label = "com.apple.root.utility-qos", .dq_serialnum = 8, ), _DISPATCH_ROOT_QUEUE_ENTRY(UTILITY, DISPATCH_PRIORITY_FLAG_OVERCOMMIT, .dq_label = "com.apple.root.utility-qos.overcommit", .dq_serialnum = 9, ), _DISPATCH_ROOT_QUEUE_ENTRY(DEFAULT, DISPATCH_PRIORITY_FLAG_FALLBACK, .dq_label = "com.apple.root.default-qos", .dq_serialnum = 10, ), _DISPATCH_ROOT_QUEUE_ENTRY(DEFAULT, DISPATCH_PRIORITY_FLAG_FALLBACK | DISPATCH_PRIORITY_FLAG_OVERCOMMIT, .dq_label = "com.apple.root.default-qos.overcommit", .dq_serialnum = 11, ), _DISPATCH_ROOT_QUEUE_ENTRY(USER_INITIATED, 0, .dq_label = "com.apple.root.user-initiated-qos", .dq_serialnum = 12, ), _DISPATCH_ROOT_QUEUE_ENTRY(USER_INITIATED, DISPATCH_PRIORITY_FLAG_OVERCOMMIT, .dq_label = "com.apple.root.user-initiated-qos.overcommit", .dq_serialnum = 13, ), _DISPATCH_ROOT_QUEUE_ENTRY(USER_INTERACTIVE, 0, .dq_label = "com.apple.root.user-interactive-qos", .dq_serialnum = 14, ), _DISPATCH_ROOT_QUEUE_ENTRY(USER_INTERACTIVE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT, .dq_label = "com.apple.root.user-interactive-qos.overcommit", .dq_serialnum = 15, ), }; 返回值就是下面两个值:即是tq的值 _DISPATCH_ROOT_QUEUE_ENTRY(DEFAULT, DISPATCH_PRIORITY_FLAG_FALLBACK, .dq_label = "com.apple.root.default-qos", .dq_serialnum = 10, ), _DISPATCH_ROOT_QUEUE_ENTRY(DEFAULT, DISPATCH_PRIORITY_FLAG_FALLBACK | DISPATCH_PRIORITY_FLAG_OVERCOMMIT, .dq_label = "com.apple.root.default-qos.overcommit", .dq_serialnum = 11, ), */ //tq模板式的创建 tq = _dispatch_get_root_queue( qos == DISPATCH_QOS_UNSPECIFIED ? DISPATCH_QOS_DEFAULT : qos, overcommit == _dispatch_queue_attr_overcommit_enabled)->_as_dq; // 0 1 if (unlikely(!tq)) { DISPATCH_CLIENT_CRASH(qos, "Invalid queue attribute"); } } if (legacy) { // if any of these attributes is specified, use non legacy classes if (dqai.dqai_inactive || dqai.dqai_autorelease_frequency) { legacy = false; } } const void *vtable; dispatch_queue_flags_t dqf = legacy ? DQF_MUTABLE : 0; // 通过dqai.dqai_concurrent 来区分并发和串行 if (dqai.dqai_concurrent) { //并发 vtable = DISPATCH_VTABLE(queue_concurrent); } else { //串行 vtable = DISPATCH_VTABLE(queue_serial); } switch (dqai.dqai_autorelease_frequency) { case DISPATCH_AUTORELEASE_FREQUENCY_NEVER: dqf |= DQF_AUTORELEASE_NEVER; break; case DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM: dqf |= DQF_AUTORELEASE_ALWAYS; break; } if (label) { const char *tmp = _dispatch_strdup_if_mutable(label); if (tmp != label) { dqf |= DQF_LABEL_NEEDS_FREE; label = tmp; } } // 开辟内存 - 生成响应的对象 queue dispatch_lane_t dq = _dispatch_object_alloc(vtable, sizeof(struct dispatch_lane_s)); /* 联合体: typedef union { struct _os_object_s *_os_obj; struct dispatch_object_s *_do; struct dispatch_queue_s *_dq; struct dispatch_queue_attr_s *_dqa; struct dispatch_group_s *_dg; struct dispatch_source_s *_ds; struct dispatch_mach_s *_dm; struct dispatch_mach_msg_s *_dmsg; struct dispatch_semaphore_s *_dsema; struct dispatch_data_s *_ddata; struct dispatch_io_s *_dchannel; } dispatch_object_t DISPATCH_TRANSPARENT_UNION; */ //_dispatch_queue_init(dispatch_queue_class_t dqu, dispatch_queue_flags_t dqf, uint16_t width, uint64_t initial_state_bits) // uint16_t width 传值: dqai.dqai_concurrent ?DISPATCH_QUEUE_WIDTH_MAX : 1 //如果是并发队列 width传DISPATCH_QUEUE_WIDTH_MAX ,串行队列width传 1. //几个宏定义: //#define DISPATCH_QUEUE_WIDTH_FULL 0x1000ull //#define DISPATCH_QUEUE_WIDTH_POOL (DISPATCH_QUEUE_WIDTH_FULL - 1) 这个是给queue_global使用 //#define DISPATCH_QUEUE_WIDTH_MAX (DISPATCH_QUEUE_WIDTH_FULL - 2) 并发队列使用 // 构造方法: _dispatch_queue_init(dq, dqf, dqai.dqai_concurrent ?DISPATCH_QUEUE_WIDTH_MAX : 1, DISPATCH_QUEUE_ROLE_INNER | (dqai.dqai_inactive ? DISPATCH_QUEUE_INACTIVE : 0)); // 标签 dq->dq_label = label; // 优先级 dq->dq_priority = _dispatch_priority_make((dispatch_qos_t)dqai.dqai_qos, dqai.dqai_relpri); if (overcommit == _dispatch_queue_attr_overcommit_enabled) { dq->dq_priority |= DISPATCH_PRIORITY_FLAG_OVERCOMMIT; } if (!dqai.dqai_inactive) { _dispatch_queue_priority_inherit_from_target(dq, tq); _dispatch_lane_inherit_wlh_from_target(dq, tq); } _dispatch_retain(tq); dq->do_targetq = tq; _dispatch_object_debug(dq, "%s", __func__); return _dispatch_trace_queue_create(dq)._dq; }
-
搜索_dispatch_queue_attr_to_info (从上面知道这应该是个结构体类型的)与 dispatch_queue_attr_info_t
typedef struct dispatch_queue_attr_info_s { dispatch_qos_t dqai_qos : 8; int dqai_relpri : 8; uint16_t dqai_overcommit:2; uint16_t dqai_autorelease_frequency:2; uint16_t dqai_concurrent:1; uint16_t dqai_inactive:1; } dispatch_queue_attr_info_t; dispatch_queue_attr_info_t _dispatch_queue_attr_to_info(dispatch_queue_attr_t dqa) { //创建一个新的dqai结构体 dispatch_queue_attr_info_t dqai = { }; //判断dqa是否存在,不存在则直接返回, //直接返回????? //我们串行队列传进来的值是什么? //#define DISPATCH_QUEUE_SERIAL NULL //传进来的是NULL,所以此处返回的是一个空值的结构体 if (!dqa) return dqai; //如果不是串行队列,那么进行下面的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 //dqa结构体位域赋值 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_lane_create_with_target代码去接着分析!!!!
2.主队列与全局队列的创建
1.dispatch_get_global_queue(0, 0)
dispatch_queue_global_t
dispatch_get_global_queue(long identifier, unsigned long flags);
typedef struct dispatch_queue_global_s *dispatch_queue_global_t;
struct dispatch_queue_global_s _dispatch_root_queues[] = {
#define _DISPATCH_ROOT_QUEUE_IDX(n, flags) \
((flags & DISPATCH_PRIORITY_FLAG_OVERCOMMIT) ? \
DISPATCH_ROOT_QUEUE_IDX_##n##_QOS_OVERCOMMIT : \
DISPATCH_ROOT_QUEUE_IDX_##n##_QOS)
#define _DISPATCH_ROOT_QUEUE_ENTRY(n, flags, ...) \
[_DISPATCH_ROOT_QUEUE_IDX(n, flags)] = { \
DISPATCH_GLOBAL_OBJECT_HEADER(queue_global), \
.dq_state = DISPATCH_ROOT_QUEUE_STATE_INIT_VALUE, \
.do_ctxt = _dispatch_root_queue_ctxt(_DISPATCH_ROOT_QUEUE_IDX(n, flags)), \
.dq_atomic_flags = DQF_WIDTH(DISPATCH_QUEUE_WIDTH_POOL), \
.dq_priority = flags | ((flags & DISPATCH_PRIORITY_FLAG_FALLBACK) ? \
_dispatch_priority_make_fallback(DISPATCH_QOS_##n) : \
_dispatch_priority_make(DISPATCH_QOS_##n, 0)), \
__VA_ARGS__ \
}
_DISPATCH_ROOT_QUEUE_ENTRY(MAINTENANCE, 0,
.dq_label = "com.apple.root.maintenance-qos",
.dq_serialnum = 4,
),
_DISPATCH_ROOT_QUEUE_ENTRY(MAINTENANCE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
.dq_label = "com.apple.root.maintenance-qos.overcommit",
.dq_serialnum = 5,
),
_DISPATCH_ROOT_QUEUE_ENTRY(BACKGROUND, 0,
.dq_label = "com.apple.root.background-qos",
.dq_serialnum = 6,
),
_DISPATCH_ROOT_QUEUE_ENTRY(BACKGROUND, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
.dq_label = "com.apple.root.background-qos.overcommit",
.dq_serialnum = 7,
),
_DISPATCH_ROOT_QUEUE_ENTRY(UTILITY, 0,
.dq_label = "com.apple.root.utility-qos",
.dq_serialnum = 8,
),
_DISPATCH_ROOT_QUEUE_ENTRY(UTILITY, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
.dq_label = "com.apple.root.utility-qos.overcommit",
.dq_serialnum = 9,
),
_DISPATCH_ROOT_QUEUE_ENTRY(DEFAULT, DISPATCH_PRIORITY_FLAG_FALLBACK,
.dq_label = "com.apple.root.default-qos",
.dq_serialnum = 10,
),
_DISPATCH_ROOT_QUEUE_ENTRY(DEFAULT,
DISPATCH_PRIORITY_FLAG_FALLBACK | DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
.dq_label = "com.apple.root.default-qos.overcommit",
.dq_serialnum = 11,
),
_DISPATCH_ROOT_QUEUE_ENTRY(USER_INITIATED, 0,
.dq_label = "com.apple.root.user-initiated-qos",
.dq_serialnum = 12,
),
_DISPATCH_ROOT_QUEUE_ENTRY(USER_INITIATED, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
.dq_label = "com.apple.root.user-initiated-qos.overcommit",
.dq_serialnum = 13,
),
_DISPATCH_ROOT_QUEUE_ENTRY(USER_INTERACTIVE, 0,
.dq_label = "com.apple.root.user-interactive-qos",
.dq_serialnum = 14,
),
_DISPATCH_ROOT_QUEUE_ENTRY(USER_INTERACTIVE, DISPATCH_PRIORITY_FLAG_OVERCOMMIT,
.dq_label = "com.apple.root.user-interactive-qos.overcommit",
.dq_serialnum = 15,
),
};
//global_queue也是使用模板式创建
2.dispatch_get_main_queue()
dispatch_queue_main_t
dispatch_get_main_queue(void)
{
return DISPATCH_GLOBAL_OBJECT(dispatch_queue_main_t, _dispatch_main_q);
}
typedef struct dispatch_queue_static_s *dispatch_queue_main_t;
struct dispatch_queue_static_s _dispatch_main_q = {
DISPATCH_GLOBAL_OBJECT_HEADER(queue_main),
#if !DISPATCH_USE_RESOLVERS
.do_targetq = _dispatch_get_default_queue(true),
#endif
.dq_state = DISPATCH_QUEUE_STATE_INIT_VALUE(1) |
DISPATCH_QUEUE_ROLE_BASE_ANON,
.dq_label = "com.apple.main-thread",
.dq_atomic_flags = DQF_THREAD_BOUND | DQF_WIDTH(1),
.dq_serialnum = 1, //从这里我们也能看出来,主队列是串行队列
};
//struct dispatch_queue_static_s 主队列使用一个静态的来创建
3._dispatch_root_queues[]的创建.
-
这个创建过程在我们加载动态库libdispatch_dyld时创建.
//创建 void _dispatch_introspection_init(void) { _dispatch_introspection.debug_queue_inversions = _dispatch_getenv_bool("LIBDISPATCH_DEBUG_QUEUE_INVERSIONS", false); // Hack to determine queue TSD offset from start of pthread structure uintptr_t thread = _dispatch_thread_self(); thread_identifier_info_data_t tiid; mach_msg_type_number_t cnt = THREAD_IDENTIFIER_INFO_COUNT; kern_return_t kr = thread_info(pthread_mach_thread_np((void*)thread), THREAD_IDENTIFIER_INFO, (thread_info_t)&tiid, &cnt); if (!dispatch_assume_zero(kr)) { _dispatch_introspection.thread_queue_offset = (void*)(uintptr_t)tiid.dispatch_qaddr - (void*)thread; } _dispatch_thread_key_create(&dispatch_introspection_key, _dispatch_introspection_thread_remove); _dispatch_introspection_thread_add(); // add main thread //循环创建_dispatch_root_queues[i]; for (size_t i = 0; i < DISPATCH_ROOT_QUEUE_COUNT; i++) { _dispatch_trace_queue_create(&_dispatch_root_queues[i]); } #if DISPATCH_USE_MGR_THREAD && DISPATCH_USE_PTHREAD_ROOT_QUEUES _dispatch_trace_queue_create(_dispatch_mgr_q.do_targetq); #endif _dispatch_trace_queue_create(&_dispatch_main_q);//主队列创建 _dispatch_trace_queue_create(&_dispatch_mgr_q); } //创建方法 static inline dispatch_queue_class_t _dispatch_trace_queue_create(dispatch_queue_class_t dqu) { _dispatch_only_if_ktrace_enabled({ uint64_t dq_label[4] = {0}; // So that we get the right null termination dispatch_queue_t dq = dqu._dq; strncpy((char *)dq_label, (char *)dq->dq_label ?: "", sizeof(dq_label)); _dispatch_ktrace2(DISPATCH_QOS_TRACE_queue_creation_start, dq->dq_serialnum, _dispatch_priority_to_pp_prefer_fallback(dq->dq_priority)); _dispatch_ktrace4(DISPATCH_QOS_TRACE_queue_creation_end, dq_label[0], dq_label[1], dq_label[2], dq_label[3]); }); return _dispatch_introspection_queue_create(dqu); }
-
主队列是在初始化的时候,单独创建的,并未使用_dispatch_root_queues[]模板创建!其他均是通过_dispatch_root_queues[]创建.
至此,GCD的队列创建流程就探索完了,写的很乱,仔细的去分析哦!下一篇会去看和函数相关的知识,敬请期待…
本文地址:https://blog.csdn.net/weixin_39950838/article/details/106528252