GCD debugDescription锁定密钥的串行队列值?

时间:2013-12-27 08:05:35

标签: ios objective-c grand-central-dispatch

我正在使用GCD对SQL数据库执行大量数据提交和数据读取操作,我创建了串行队列并执行我正在使用dispatch_async的操作。

队列创建代码:

  self.dataBaseQueue = dispatch_queue_create("com.myAPP.dataBaseQueue", DISPATCH_QUEUE_SERIAL);

执行代码

  dispatch_async(self.dataBaseQueue, codeblock);

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 =1locked =0是什么意思?

1 个答案:

答案 0 :(得分:2)

正如yurish所指出的那些消息来源可用,但无论如何“让我为你做谷歌”,还有一些(希望是有用的)补充分析。

首先,一些背景......在object_internal.h中,您可以找到以下#define

#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一起使用,以使其作为锁定位(在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_INTERVALlocked对应dou._do->do_suspend_cnt & 1,因此很容易得出结论,是的,do_suspend_cnt正在做这个双重职责由上述#define暗示。

现在,我们可以在消息来源中观察到do_suspend_cnt仅在queue.c中的少数几个地方被引用。在队列结构的初始化中提到了它。它也被barrier调用使用,但仅在DISPATCH_OBJECT_SUSPEND_INTERVAL递增和递减方面使用,所以这并不重要(至少不是关于锁定位 - 有人可能认为这个障碍很有意思dispatch是通过挂起队列来实现的,直到屏障调用返回,但这不是OP所要求的)。

我看到的剩余提及是在_dispatch_wakeup中,它似乎在将下一个工作项从队列中移除之前以原子方式设置锁定位(有道理,对吗?不要从队列中取出以下内容一个地方同时)然后再次在_dispatch_queue_invoke中减去锁定位,似乎在_dispatch_wakeup中平衡它的设置。最后,我们在_dispatch_queue_cleanup2中看到它(在表面上)看起来像主要调度队列的一次性拆解工作。

所以你有它。调试描述中locked =的出现暴露了libdispatch似乎用于保护其内部数据结构免于并发突变的内部锁定位的状态。作为libdispatch的用户,这可能对您没有任何影响。