ios - GCD调试锁定 key 的串行队列值的描述?

标签 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);

代码块包含数据库操作读或写。

现在,当我记录队列的 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的含义是什么?

最佳答案

正如尤里什指出的那样,来源是可用的,但无论如何“让我为你谷歌一下”,并添加一些(希望有帮助的)分析。

首先,一些背景...在 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_INTERVALlocked对应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/

相关文章:

ios - 收到推送通知时打开特定选项卡并在 uiwebview 中启动特定网址

Objective-C block 和变量范围

objective-c - 如何用一堆 CAEmitterCells 获得更小的尾部(淡出和/或缩小)

iphone - 生成调度源计时器事件时发生内存泄漏

ios - 使用 Phonegap 实现 iOS 的 PushPlugin

ios - 如何使 UILabel 调整大小以适合文本

ios - 代码不在窗口层次结构 Root View 中

ios - 具有自动布局和附件 View 的自定义 UITableViewCell

ios - 在 iOS 中高效同步数据

ios - 在 ARC 下使用 dispatch_write 将 NSData 写入后台唯一文件