我正在使用 GCD 在 SQL 数据库上执行大量数据提交和数据读取操作,我创建了串行队列并使用 dispatch_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 }
那么locked =1
和locked =0
的含义是什么?
最佳答案
正如尤里什指出的那样,来源是可用的,但无论如何“让我为你谷歌一下”,并添加一些(希望有帮助的)分析。
首先,一些背景...在 object_internal.h
您可以找到以下#define
s:
#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 中)又作为挂起计数(在其余位中)。
然后,在 object.c
中结束我们可以看到这个调试消息业务实际上是在哪里实现的:
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_cnt
对应dou._do->do_suspend_cnt / DISPATCH_OBJECT_SUSPEND_INTERVAL
和locked
对应dou._do->do_suspend_cnt & 1
所以很容易得出结论,是的,do_suspend_cnt
正在履行上述#define
暗示的双重职责s。
现在,无需了解太多细节,我们就可以在源代码中观察到 do_suspend_cnt
仅在 queue.c
中的少数地方被引用。在队列结构的初始化中提到过。 barrier
也使用它。调用,但仅限于将其递增和递减 DISPATCH_OBJECT_SUSPEND_INTERVAL
,所以这并不有趣(至少不涉及锁位——人们可能会认为有趣的是,屏障调度是通过挂起队列直到屏障调用返回来实现的,但这不是OP所要求的)。
我看到的其余提及位于 _dispatch_wakeup
它似乎在从队列中取出下一个工作项之前自动设置锁定位(有道理,对吗?不要同时从多个地方从队列中取出内容),然后在 _dispatch_queue_invoke
中再次设置锁定位。减去锁定位,似乎是为了平衡_dispatch_wakeup
中它的设置。最后,我们看到_dispatch_queue_cleanup2
中提到了它。 (表面上)这看起来像是主调度队列的一次性拆卸工作。
所以你已经得到它了。外观locked =
调试描述中公开了内部锁定位的状态 libdispatch
似乎是用来保护其内部数据结构免受并发突变的影响。作为 libdispatch
的用户,这可能对您没有任何影响。 .
关于ios - GCD调试锁定 key 的串行队列值的描述?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20797145/