当前位置: 移动技术网 > 移动技术>移动开发>IOS > 荐 iOS底层原理篇(九)----GCD底层原理(一)

荐 iOS底层原理篇(九)----GCD底层原理(一)

2020年07月23日  | 移动技术网移动技术  | 我要评论

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_createdispatch_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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网