Ios GCD调试锁定密钥的串行队列值说明?
我正在使用GCD对SQL数据库执行大量数据提交和数据读取操作,我创建了串行队列,并使用Ios GCD调试锁定密钥的串行队列值说明?,ios,objective-c,grand-central-dispatch,Ios,Objective C,Grand Central Dispatch,我正在使用GCD对SQL数据库执行大量数据提交和数据读取操作,我创建了串行队列,并使用dispatch\u async执行操作 队列创建代码: self.dataBaseQueue = dispatch_queue_create("com.myAPP.dataBaseQueue", DISPATCH_QUEUE_SERIAL); 执行代码 dispatch_async(self.dataBaseQueue, codeblock); 代码块包含数据库操作读或写 现在,当我记录正在打印的
dispatch\u async
执行操作
队列创建代码:
self.dataBaseQueue = dispatch_queue_create("com.myAPP.dataBaseQueue", DISPATCH_QUEUE_SERIAL);
执行代码
dispatch_async(self.dataBaseQueue, codeblock);
代码块包含数据库操作读或写
现在,当我记录正在打印的队列的debugDescription
时
OS_dispatch_queue: com.myAPP.dataBaseQueue[0x1cd58ae0] = { xrefcnt = 0x1, refcnt = 0x1, suspend_cnt = 0x0, **locked = 0**, target = com.apple.root.default-overcommit-priority[0x3d335300], width = 0x0, running = 0x0, barrier = 0 }
OS_dispatch_queue: com.myAPP.dataBaseQueue[0x1cd58ae0] = { xrefcnt = 0x1, refcnt = 0x1, suspend_cnt = 0x0, **locked = 1**, target = com.apple.root.default-overcommit-priority[0x3d335300], width = 0x0, running = 0x0, barrier = 0 }
经过一些操作后,它正在打印
OS_dispatch_queue: com.myAPP.dataBaseQueue[0x1cd58ae0] = { xrefcnt = 0x1, refcnt = 0x1, suspend_cnt = 0x0, **locked = 0**, target = com.apple.root.default-overcommit-priority[0x3d335300], width = 0x0, running = 0x0, barrier = 0 }
OS_dispatch_queue: com.myAPP.dataBaseQueue[0x1cd58ae0] = { xrefcnt = 0x1, refcnt = 0x1, suspend_cnt = 0x0, **locked = 1**, target = com.apple.root.default-overcommit-priority[0x3d335300], width = 0x0, running = 0x0, barrier = 0 }
那么
locked=1
和locked=0
的含义是什么呢?正如尤里什指出的那样,这些来源是可用的,但“让我为您搜索一下”,并添加了一些(希望有帮助的)分析
首先,一些背景。。。在中,您可以找到以下定义:
#define DISPATCH_OBJECT_SUSPEND_LOCK 1u
#define DISPATCH_OBJECT_SUSPEND_INTERVAL 2u
#define DISPATCH_OBJECT_SUSPENDED(x) \
((x)->do_suspend_cnt >= DISPATCH_OBJECT_SUSPEND_INTERVAL)
这表示单个值将与这些#define
s一起使用,以使其作为锁定位(在LSB中)和挂起计数(在其余位中)执行双重任务
然后,在中,我们可以看到调试消息业务的实际实现位置:
size_t
_dispatch_object_debug_attr(dispatch_object_t dou, char* buf, size_t bufsiz)
{
return snprintf(buf, bufsiz, "xrefcnt = 0x%x, refcnt = 0x%x, "
"suspend_cnt = 0x%x, locked = %d, ", dou._do->do_xref_cnt + 1,
dou._do->do_ref_cnt + 1,
dou._do->do_suspend_cnt / DISPATCH_OBJECT_SUSPEND_INTERVAL,
dou._do->do_suspend_cnt & 1);
}
果然,我们看到suspend\u cnt
对应于dou.\u do->do\u suspend\u cnt/DISPATCH\u OBJECT\u suspend\u INTERVAL
和locked
对应于dou.\u do->do\u suspend\u cnt&1
,所以很容易得出结论,是的,do_suspend_cnt
正在履行上述\define
s所暗示的双重职责
现在,不需要太多细节,我们可以在源代码中看到,do\u suspend\u cnt
仅在中的少数地方被引用。队列结构的初始化中提到了这一点。它也被barrier
调用使用,但只是通过DISPATCH\u OBJECT\u SUSPEND\u INTERVAL
对其进行递增和递减,所以这并不有趣(至少对于锁位而言,人们可能会觉得有趣的是,通过将队列挂起直到屏障调用返回,但这不是OP所要求的)来实现屏障调度。
我看到的其余内容出现在\u dispatch\u wakeup
中,它似乎是在从队列中取出下一个工作项之前自动设置锁位的(有道理,对吧?不要同时从多个位置取出东西)然后在\u dispatch\u queue\u invoke
中再次减去锁位,似乎是为了平衡\u dispatch\u wakeup
中的锁位设置。最后,我们看到在\u dispatch\u queue\u cleanup2
中提到的锁位(表面上)类似于主调度队列的一次性拆卸工作
在调试描述中,
locked=
的出现暴露了内部锁位的状态,libdispatch
似乎是用来保护其内部数据结构免受并发变异的。作为libdispatch
的用户,这可能对您没有任何影响ode>debugDescription?它是dispatch_debug的输出吗?是的,它类似于dispatch_debug。您可能会发现libdispatch库的源代码非常有用: