如下仅是对Dispatch Queue的分析。数组
GCD队列是按照层级关系来组织的: bash
GCD中的队列Dispatch Queue是经过链表和结构体实现的。网络
// 声明一个结构体,能够看出gcd内部name_t和name_s之间的关系:name_s是一个指向结构体name_t的指针。一个东西
#define DISPATCH_DECL(name) typedef struct name##_s *name##_t
复制代码
// dispatch_object_t能够是联合内部任何一种结构(仅保留Queue相关的)
typedef union {
struct _os_object_s *_os_obj;// 基类
struct dispatch_object_s *_do;// 基类继承os_object
struct dispatch_continuation_s *_dc;// 任务结构
struct dispatch_queue_s *_dq;// 队列结构
struct dispatch_queue_attr_s *_dqa;// 队列相关属性
struct dispatch_group_s *_dg;// group结构
struct dispatch_semaphore_s *_dsema;// 信号量
} dispatch_object_t DISPATCH_TRANSPARENT_UNION;
复制代码
// 系统对象结构或者说系统基类
typedef struct _os_object_s {
_OS_OBJECT_HEADER(
const _os_object_vtable_s *os_obj_isa,
os_obj_ref_cnt,
os_obj_xref_cnt);
} _os_object_s;
// 系统对象头部定义宏
#define _OS_OBJECT_HEADER(isa, ref_cnt, xref_cnt)
isa; // isa指针
int volatile ref_cnt; // gcd对象内部引用计数
int volatile xref_cnt // gcd对象外部引用计数(内外部都要减到0时,对象会被释放)
复制代码
struct dispatch_object_s {
_DISPATCH_OBJECT_HEADER(object);
};
#define _DISPATCH_OBJECT_HEADER(x)
struct _os_object_s _as_os_obj[0]; //继承自os_object
OS_OBJECT_STRUCT_HEADER(dispatch_##x);
struct dispatch_##x##_s *volatile do_next; //链表的next
struct dispatch_queue_s *do_targetq;
void *do_ctxt;
void *do_finalizer
复制代码
// GCD中的任务是先被封装成dispatch_continuation,再提交到队列中的。该dispatch_continuation用于存储任务所在的dispatch_group和一些其余信息,至关于通常常说的执行上下文。
typedef struct dispatch_continuation_s {
struct dispatch_object_s _as_do[0];//继承自dispatch_object
DISPATCH_CONTINUATION_HEADER(continuation);//continuation的一些属性
} *dispatch_continuation_t;
#define DISPATCH_CONTINUATION_HEADER(x)
union {
const void *do_vtable;
uintptr_t dc_flags;
};
union {
pthread_priority_t dc_priority;
int dc_cache_cnt;
uintptr_t dc_pad;
};
struct voucher_s *dc_voucher;
struct dispatch_##x##_s *volatile do_next;
dispatch_function_t dc_func; // 任务函数(block会转为function)
void *dc_ctxt; // 执行环境:函数参数
void *dc_data;
void *dc_other
复制代码
// 队列结构体
struct dispatch_queue_s {
_DISPATCH_QUEUE_HEADER(queue);
DISPATCH_QUEUE_CACHELINE_PADDING; // for static queues only
} DISPATCH_ATOMIC64_ALIGN;
#define _DISPATCH_QUEUE_HEADER(x)
struct os_mpsc_queue_s _as_oq[0];
DISPATCH_OBJECT_HEADER(x); //继承父类的属性
uint32_t dq_side_suspend_cnt;
DISPATCH_UNION_LE(uint32_t volatile dq_atomic_flags,
const uint16_t dq_width, //宽度:串行1,并行>1
const uint16_t __dq_opaque
);
DISPATCH_INTROSPECTION_QUEUE_HEADER
#define DISPATCH_INTROSPECTION_QUEUE_HEADER
TAILQ_ENTRY(dispatch_queue_s) diq_list;
dispatch_unfair_lock_s diq_order_top_head_lock;
dispatch_unfair_lock_s diq_order_bottom_head_lock;
TAILQ_HEAD(, dispatch_queue_order_entry_s) diq_order_top_head; // 队列链表头结点
TAILQ_HEAD(, dispatch_queue_order_entry_s) diq_order_bottom_head // 尾节点
// 队列属性
struct dispatch_queue_attr_s {
OS_OBJECT_STRUCT_HEADER(dispatch_queue_attr);
};
复制代码
typedef struct dispatch_continuation_vtable_s {
_OS_OBJECT_CLASS_HEADER();
DISPATCH_INVOKABLE_VTABLE_HEADER(dispatch_continuation);
} const *dispatch_continuation_vtable_t;
#define DISPATCH_INVOKABLE_VTABLE_HEADER(x) \
unsigned long const do_type; // 类型
const char *const do_kind; // 种类描述
void (*const do_invoke)(struct x##_s *, dispatch_invoke_context_t, \
dispatch_invoke_flags_t); // 执行函数
void (*const do_push)(struct x##_s *, dispatch_object_t, \
dispatch_qos_t)// 推入队列函数
串行队列实例:
DISPATCH_VTABLE_SUBCLASS_INSTANCE(queue_serial, queue,
.do_type = DISPATCH_QUEUE_SERIAL_TYPE,
.do_kind = "serial-queue",
.do_dispose = _dispatch_queue_dispose,
.do_suspend = _dispatch_queue_suspend,
.do_resume = _dispatch_queue_resume,
.do_finalize_activation = _dispatch_queue_finalize_activation,
.do_push = _dispatch_queue_push,
.do_invoke = _dispatch_queue_invoke,
.do_wakeup = _dispatch_queue_wakeup,
.do_debug = dispatch_queue_debug,
.do_set_targetq = _dispatch_queue_set_target_queue,
);
复制代码
FIFO队列的管理是经过dispatch_async等函数来实现的(操做头尾节点)。 在GCD中,可执行的任务有两种方式实现:Block、Function。所以和任务相关的API通常是有两种形式的:数据结构
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
dispatch_async_f(dispatch_queue_t queue,
void *_Nullable context,
dispatch_function_t work);
复制代码
dispatch_queue_t
dispatch_get_global_queue(long priority, unsigned long flags)
{
// 形成空值返回的缘由
if (flags & ~(unsigned long)DISPATCH_QUEUE_OVERCOMMIT) {
return DISPATCH_BAD_INPUT;
}
// 转化优先级
dispatch_qos_t qos = _dispatch_qos_from_queue_priority(priority);
#if !HAVE_PTHREAD_WORKQUEUE_QOS
if (qos == QOS_CLASS_MAINTENANCE) {
qos = DISPATCH_QOS_BACKGROUND;
} else if (qos == QOS_CLASS_USER_INTERACTIVE) {
qos = DISPATCH_QOS_USER_INITIATED;
}
#endif
if (qos == DISPATCH_QOS_UNSPECIFIED) {
return DISPATCH_BAD_INPUT;
}
// flags传0时: overcommit = NO
// 从系统队列数组中获取对应优先级的数组
return _dispatch_get_root_queue(qos, flags & DISPATCH_QUEUE_OVERCOMMIT);
}
复制代码
static inline dispatch_queue_t
_dispatch_get_root_queue(dispatch_qos_t qos, bool overcommit)
{
// _dispatch_root_queues是系统中存储不一样级别队列的数组,返回数组中指定index的队列,overcommit=0/1
return &_dispatch_root_queues[2 * (qos - 1) + overcommit];
}
// 数组中的队列
struct dispatch_queue_s _dispatch_root_queues[];
// skip zero
// 1 - main_q 主队列
// 2 - mgr_q gcd内部管理队列
// 3 - mgr_root_q
// 4,5,6,7,8,9,10,11,12,13,14,15 - global queues
// 以后是手动建立的队列
复制代码
dispatch_qos_t:
#define DISPATCH_QOS_UNSPECIFIED ((dispatch_qos_t)0)
#define DISPATCH_QOS_MAINTENANCE ((dispatch_qos_t)1)
#define DISPATCH_QOS_BACKGROUND ((dispatch_qos_t)2)
#define DISPATCH_QOS_UTILITY ((dispatch_qos_t)3)
#define DISPATCH_QOS_DEFAULT ((dispatch_qos_t)4)
#define DISPATCH_QOS_USER_INITIATED ((dispatch_qos_t)5)
#define DISPATCH_QOS_USER_INTERACTIVE ((dispatch_qos_t)6)
系统中队列的优先级枚举:
enum {
DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS = 0,
DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS_OVERCOMMIT,
DISPATCH_ROOT_QUEUE_IDX_BACKGROUND_QOS,
DISPATCH_ROOT_QUEUE_IDX_BACKGROUND_QOS_OVERCOMMIT,
DISPATCH_ROOT_QUEUE_IDX_UTILITY_QOS,
DISPATCH_ROOT_QUEUE_IDX_UTILITY_QOS_OVERCOMMIT,
DISPATCH_ROOT_QUEUE_IDX_DEFAULT_QOS,
DISPATCH_ROOT_QUEUE_IDX_DEFAULT_QOS_OVERCOMMIT,
DISPATCH_ROOT_QUEUE_IDX_USER_INITIATED_QOS,
DISPATCH_ROOT_QUEUE_IDX_USER_INITIATED_QOS_OVERCOMMIT,
DISPATCH_ROOT_QUEUE_IDX_USER_INTERACTIVE_QOS,
DISPATCH_ROOT_QUEUE_IDX_USER_INTERACTIVE_QOS_OVERCOMMIT,
_DISPATCH_ROOT_QUEUE_IDX_COUNT,
};
复制代码
/*!
* @enum 队列的一个标志位
*
* @constant DISPATCH_QUEUE_OVERCOMMIT
* 表示当线程池中线程用完(eg:64个线程),无论系统多么繁忙,不会等待,这个队列都会强制建立一个新的线程来执行任务。也就是说能够建立超过内核数目的线程。
*/
enum {
DISPATCH_QUEUE_OVERCOMMIT = 0x2ull,
};
复制代码
struct dispatch_queue_s _dispatch_main_q = {
DISPATCH_GLOBAL_OBJECT_HEADER(queue_main),
#if !DISPATCH_USE_RESOLVERS
// 主队列的目标队列是:默认优先级,overcommit的globalQueue
.do_targetq = &_dispatch_root_queues[
DISPATCH_ROOT_QUEUE_IDX_DEFAULT_QOS_OVERCOMMIT],
#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_CANNOT_TRYSYNC | DQF_WIDTH(1),
.dq_serialnum = 1,
};
复制代码
dispatch_queue_t
dispatch_queue_create(const char *label, dispatch_queue_attr_t attr)
{
return _dispatch_queue_create_with_target(label, attr,
DISPATCH_TARGET_QUEUE_DEFAULT(NULL), true);
}
static dispatch_queue_t
_dispatch_queue_create_with_target(const char *label, dispatch_queue_attr_t dqa,
dispatch_queue_t tq, bool legacy)
{
//
// Step 1: Normalize arguments (qos, overcommit, tq)
//
dispatch_qos_t qos = _dispatch_priority_qos(dqa->dqa_qos_and_relpri);
_dispatch_queue_attr_overcommit_t overcommit = dqa->dqa_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 && !tq->do_targetq &&
tq->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
// 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) {
dispatch_qos_t tq_qos = _dispatch_priority_qos(tq->dq_priority);
tq = _dispatch_get_root_queue(tq_qos,
overcommit == _dispatch_queue_attr_overcommit_enabled);
} else {
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) {
//
overcommit = dqa->dqa_concurrent ?
_dispatch_queue_attr_overcommit_disabled :
_dispatch_queue_attr_overcommit_enabled;
}
}
if (!tq) {
// 手动建立队列,未设置目标队列,则从系统队列中获取一个队列(默认优先级的globalQueue)做为目标队列,若是建立的是串行队列,则目标队列是overcommit,不然不是(👆)
tq = _dispatch_get_root_queue(
qos == DISPATCH_QOS_UNSPECIFIED ? DISPATCH_QOS_DEFAULT : qos,
overcommit == _dispatch_queue_attr_overcommit_enabled);
}
//
// Step 2: Initialize the queue
//
if (legacy) {
// if any of these attributes is specified, use non legacy classes
if (dqa->dqa_inactive || dqa->dqa_autorelease_frequency) {
legacy = false;
}
}
const void *vtable;
dispatch_queue_flags_t dqf = 0;
if (legacy) {
vtable = DISPATCH_VTABLE(queue);
} else if (dqa->dqa_concurrent) {
vtable = DISPATCH_VTABLE(queue_concurrent);
} else {
vtable = DISPATCH_VTABLE(queue_serial);
}
switch (dqa->dqa_autorelease_frequency) {
case DISPATCH_AUTORELEASE_FREQUENCY_NEVER:
dqf |= DQF_AUTORELEASE_NEVER;
break;
case DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM:
dqf |= DQF_AUTORELEASE_ALWAYS;
break;
}
if (legacy) {
dqf |= DQF_LEGACY;
}
if (label) {
const char *tmp = _dispatch_strdup_if_mutable(label);
if (tmp != label) {
dqf |= DQF_LABEL_NEEDS_FREE;
label = tmp;
}
}
// 建立队列对象
// 分配空间 isa指向它的类型 相关属性赋值
dispatch_queue_t dq = _dispatch_object_alloc(vtable,
sizeof(struct dispatch_queue_s) - DISPATCH_QUEUE_CACHELINE_PAD);
// 初始化队列相关参数
_dispatch_queue_init(dq, dqf, dqa->dqa_concurrent ?
DISPATCH_QUEUE_WIDTH_MAX : 1, DISPATCH_QUEUE_ROLE_INNER |
(dqa->dqa_inactive ? DISPATCH_QUEUE_INACTIVE : 0));
dq->dq_label = label;
dq->dq_priority = dqa->dqa_qos_and_relpri;
if (!dq->dq_priority) {
// 未设置优先级的队列,优先级默认继承自它的目标队列
_dispatch_queue_priority_inherit_from_target(dq, tq);
} else if (overcommit == _dispatch_queue_attr_overcommit_enabled) {
dq->dq_priority |= DISPATCH_PRIORITY_FLAG_OVERCOMMIT;
}
if (!dqa->dqa_inactive) {
_dispatch_queue_inherit_wlh_from_target(dq, tq);
}
_dispatch_retain(tq);
// 设置目标队列
dq->do_targetq = tq;
_dispatch_object_debug(dq, "%s", __func__);
return _dispatch_introspection_queue_create(dq);
}
// 构建队列内部头尾节点等
dispatch_queue_t
_dispatch_introspection_queue_create(dispatch_queue_t dq)
{
TAILQ_INIT(&dq->diq_order_top_head);// 建立队列的头尾节点
TAILQ_INIT(&dq->diq_order_bottom_head);
_dispatch_unfair_lock_lock(&_dispatch_introspection.queues_lock);// 加锁
TAILQ_INSERT_TAIL(&_dispatch_introspection.queues, dq, diq_list);// 将队列插入到队列数组中
_dispatch_unfair_lock_unlock(&_dispatch_introspection.queues_lock);// 解锁
DISPATCH_INTROSPECTION_INTERPOSABLE_HOOK_CALLOUT(queue_create, dq);
if (DISPATCH_INTROSPECTION_HOOK_ENABLED(queue_create)) {
_dispatch_introspection_queue_create_hook(dq);
}
return dq;
}
复制代码
void
_dispatch_queue_set_target_queue(dispatch_queue_t dq, dispatch_queue_t tq)
{
// global/main queue
dispatch_assert(dq->do_ref_cnt != DISPATCH_OBJECT_GLOBAL_REFCNT &&
dq->do_targetq);
// tq为空时,设置默认的目标队列同createQ
if (unlikely(!tq)) {
bool is_concurrent_q = (dq->dq_width > 1);
tq = _dispatch_get_root_queue(DISPATCH_QOS_DEFAULT, !is_concurrent_q);
}
if (_dispatch_queue_try_inactive_suspend(dq)) {
_dispatch_object_set_target_queue_inline(dq, tq);
return dx_vtable(dq)->do_resume(dq, false);
}
if (unlikely(!_dispatch_queue_is_legacy(dq))) {
#if 1
if (_dispatch_queue_atomic_flags(dq) & DQF_TARGETED) {
DISPATCH_CLIENT_CRASH(0, "Cannot change the target of a queue "
"already targeted by other dispatch objects");
}
#endif
DISPATCH_CLIENT_CRASH(0, "Cannot change the target of this object "
"after it has been activated");
}
unsigned long type = dx_type(dq);
switch (type) {
case DISPATCH_QUEUE_LEGACY_TYPE:
#if 1
if (_dispatch_queue_atomic_flags(dq) & DQF_TARGETED) {
_dispatch_bug_deprecated("Changing the target of a queue "
"already targeted by other dispatch objects");
}
#endif
break;
case DISPATCH_SOURCE_KEVENT_TYPE:
case DISPATCH_MACH_CHANNEL_TYPE:
_dispatch_ktrace1(DISPATCH_PERF_post_activate_retarget, dq);
_dispatch_bug_deprecated("Changing the target of a source "
"after it has been activated");
break;
default:
DISPATCH_CLIENT_CRASH(type, "Unexpected dispatch object type");
}
_dispatch_retain(tq);
return _dispatch_barrier_trysync_or_async_f(dq, tq,
_dispatch_queue_legacy_set_target_queue,
DISPATCH_BARRIER_TRYSYNC_SUSPEND);
}
复制代码
// 任务是block、function走的都是同样的
void
dispatch_sync(dispatch_queue_t dq, dispatch_block_t work)
{
dispatch_sync_f(dq, work, _dispatch_Block_invoke(work));
// _dispatch_Block_invoke:block转function
}
复制代码
void
dispatch_sync_f(dispatch_queue_t dq, void *ctxt//函数参数, dispatch_function_t func)
{
// 同步任务通常不切换线程
// 若是是串行队列,则等待前面的任务执行完成才能开始执行,barrier经过信号量来实现的
if (likely(dq->dq_width == 1)) {
return dispatch_barrier_sync_f(dq, ctxt, func);
}
// 当前队列阻塞barrier或者线程数超过了队列的容量,可能须要切换线程
if (unlikely(!_dispatch_queue_try_reserve_sync_width(dq))) {
return _dispatch_sync_f_slow(dq, ctxt, func, 0);
}
// 若是想在当前串行队列中同步加入任务 死锁
_dispatch_introspection_sync_begin(dq);
if (unlikely(dq->do_targetq->do_targetq)) {
return _dispatch_sync_recurse(dq, ctxt, func, 0);
}
_dispatch_sync_invoke_and_complete(dq, ctxt, func);// 同步执行函数
}
复制代码
注意死锁: app
dispatch_async(dispatch_queue_t dq, dispatch_block_t work)
{
// 将任务包装成continuation
dispatch_continuation_t dc = _dispatch_continuation_alloc();
uintptr_t dc_flags = DISPATCH_OBJ_CONSUME_BIT;
_dispatch_continuation_init(dc, dq, work, 0, 0, dc_flags);
_dispatch_async_f2(dq, dc);// 中间省略了几步
}
static void
_dispatch_async_f2(dispatch_queue_t dq, dispatch_continuation_t dc)
{
if (slowpath(dq->dq_items_tail)) {// 若是当前队列中尾节点存在,说明当前队列中有任务了,就不须要再把任务在向上提交了,直接提交到当前队列中。
return dx_push(dq, dc, _dispatch_continuation_override_qos(dq, dc));
}
if (slowpath(!_dispatch_queue_try_acquire_async(dq))) {
return dx_push(dq, dc, _dispatch_continuation_override_qos(dq, dc));
}
// 不然须要沿着链往上提交任务
return _dispatch_async_f_redirect(dq, dc,
_dispatch_continuation_override_qos(dq, dc));
}
// 将任务转发
_dispatch_async_f_redirect(dispatch_queue_t dq,
dispatch_object_t dou, dispatch_qos_t qos)
{
dq = dq->do_targetq;
// 根据队列的继承链,将任务一层层向上提交,直到目标队列是串行队列,其实就是将任务提交到了目标队列中了。
// #define DISPATCH_QUEUE_USES_REDIRECTION(width) \
({ uint16_t _width = (width); \
_width > 1 && _width < DISPATCH_QUEUE_WIDTH_POOL; })
while (slowpath(DISPATCH_QUEUE_USES_REDIRECTION(dq->dq_width))) { // 省略中间内容
dq = dq->do_targetq;
}
dx_push(dq, dou, qos);
}
dx_push:
static inline void
_dispatch_queue_push_inline(dispatch_queue_t dq, dispatch_object_t _tail,
dispatch_qos_t qos)
{
// 更新队列尾节点指针,插入新任务节点
struct dispatch_object_s *tail = _tail._do;
dispatch_wakeup_flags_t flags = 0;
bool overriding = _dispatch_queue_need_override_retain(dq, qos);
if (unlikely(_dispatch_queue_push_update_tail(dq, tail))) {
if (!overriding) _dispatch_retain_2(dq->_as_os_obj);
_dispatch_queue_push_update_head(dq, tail);
flags = DISPATCH_WAKEUP_CONSUME_2 | DISPATCH_WAKEUP_MAKE_DIRTY;
} else if (overriding) {
flags = DISPATCH_WAKEUP_CONSUME_2;
} else {
return;
}
return dx_wakeup(dq, qos, flags);// 唤起下个任务
}
复制代码
系统中队列是按照层级关系来组织的,获取当前队列,也就是要获取执行当前代码的线程所关联的队列,因为目标队列的这种继承关系,任务会一层层向上提交至根队列,因此dispatch_get_current_queue()获取的返回结果多是当前执行环境中关联的队列中的任意一个与预期不一样,所以使用它可能会形成错误,甚至是死锁问题。异步
如如下代码:因为dispatch_get_current_queue()结果的错误会执行else语句,若是当前队列就是queue,就会形成同步等待(信号量锁实现,所以也是死锁问题)async
void func(dispatch_queue_t queue, dispatch_block_t block)
{
if (dispatch_get_current_queue() == queue) {
block();
}else{
dispatch_sync(queue, block);
}
}
复制代码
dispatch_queue_set_specific(queue,key) // 给队列设置一个关联keyide
dispatch_get_specific(key) // 获取到当前任务的执行环境(一串继承链的队列)中对应key值的队列。这个就更加准确了。函数
dispatch_queue_t q1 = dispatch_queue_create("", NULL);
dispatch_queue_t q3 = dispatch_queue_create("", NULL);
dispatch_set_target_queue(q3, q1);
static int specificKey;
CFStringRef specificValue = CFSTR("queue1");
dispatch_queue_set_specific(q1,
&specificKey,
(void*)specificValue,
(dispatch_function_t)CFRelease);
dispatch_sync(q3, ^{
dispatch_block_t block = ^{
//do something
};
// 看看关联当前这个正在执行的任务的队列链条中是否有key值是specificKey的队列即q1
CFStringRef retrievedValue = dispatch_get_specific(&specificKey);
if (retrievedValue) { // 有,直接执行block
block();
} else { // 没有,同步加到q1中,不会形成同步阻塞
dispatch_sync(q1, block);
}
});
复制代码
实现代码:oop
void *
dispatch_get_specific(const void *key)
{
if (slowpath(!key)) {
return NULL;
}
void *ctxt = NULL;
dispatch_queue_t dq = _dispatch_queue_get_current();// 获取当前任务是在哪一个队列链中执行的
while (slowpath(dq)) {// 沿着链找关联key值的队列
ctxt = _dispatch_queue_get_specific_inline(dq, key);
if (ctxt) break;
dq = dq->do_targetq;
}
return ctxt;
}
复制代码
通常当下载数据时,为了避免妨碍主线程的运行,会进行异步处理。那么每次网络下载处理都要使用GCD的线程吗?答案是否认的。若是每次下载就生成一个线程,那么极可能会产生大量的线程,很快就会用尽线程池中线程和内存。所以系统提供的异步网络通讯API,它生成一个线程专门用于异步下载,同时开启这个线程的runloop,添加port让runloop一直循环运行,这样线程就不会被销毁,当有下载任务时,该线程被唤醒执行任务,没任务就挂起等待。