【问题标题】:GCD debugDescription of serial queue value of locked key?GCD调试锁定键的串行队列值的描述?
【发布时间】:2013-12-30 21:50:15
【问题描述】:

我正在使用 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 =1locked =0是什么意思?

【问题讨论】:

  • 什么是debugDescription?是dispatch_debug的输出吗?
  • 是的,它就像 dispatch_debug。
  • 您可能会发现 libdispatch 库的来源很有帮助:libdispatch.macosforge.org

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


【解决方案1】:

正如 yurish 指出的那样,资源是可用的,但无论如何“让我为你搜索一下”,并添加了一些(希望有帮助的)分析。

首先,一些背景......在object_internal.h你可以找到以下#defines:

#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)

这表明单个值将与这些 #defines 一起使用,以便让它作为锁定位(在 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 正在执行上述@987654335 所暗示的双重职责@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 的用户,这可能对您没有任何影响。

【讨论】:

    猜你喜欢
    • 2013-10-11
    • 2012-12-17
    • 2022-08-23
    • 2021-10-24
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多