使用GCD实现的读写锁

11

我的应用程序大量使用GCD,几乎所有的操作都是通过调度处理小任务完成的。然而,底层数据模型主要是读取,只有偶尔进行写入。

我目前使用锁来防止在读取关键数据结构时发生更改。但是今天在进一步研究锁时,我发现了NSConditionLock和一些与读写锁相关的页面。后者正是我需要的。

我找到了这个实现:http://cocoaheads.byu.edu/wiki/locks。我的问题是,这个实现是否能够与GCD一起使用,因为它使用了PThreads?

2个回答

28

它仍然可以工作。 pthreads是Mac OS X上所有其他使用线程API的基础线程API。(在那之下有Mach线程激活,但那是SPI,而不是API.) 无论如何,pthread锁实际上不需要您使用pthread线程。

然而,自iOS 5以来,GCD提供了更好的替代方案:dispatch_barrier_async()。基本上,你有一个私有并发队列。你按照正常方式将所有读操作提交给它。你使用屏障例程将写操作提交给它。泰达!读写锁定。

如果您可以访问WWDC 2011会话视频210 - 掌握Grand Central Dispatch,您可以了解更多相关信息。


1
啊,我之前读到过这些屏障,但当时并没有想到实际应用(那时我几乎没有使用多线程),于是就忘了它们。谢谢,我会尝试看看能否使用它们! - Erik S
4
Mike Ash也提供了一个很好的例子,展示了如何使用GCD实现读写同步。http://www.mikeash.com/pyblog/friday-qa-2011-10-14-whats-new-in-gcd.html - Quinn Taylor

2
你可能还需要考虑为所有读写操作维护一个串行队列。然后,你可以使用dispatch_sync()将写操作分派到该队列中,以确保对数据模型的更改立即生效,并使用dispatch_async()将所有读操作分派到队列中,以确保应用程序具有良好的性能。
由于你只有一个单一的串行队列来进行所有读写操作,因此你确保在写操作期间不会发生读取操作。这比锁定要少得多,但它意味着你不能同时执行多个“读”操作。这对大多数应用程序来说不太可能成为问题。
使用dispatch_barrier_async()可能意味着你所做的写操作需要任意长的时间才能真正提交,因为必须完成队列中的所有预先存在的任务,然后才能执行你的屏障块。

哦,我甚至没有意识到串行队列上可以使用异步调度。这听起来像是一个有趣的想法... 所有的读取都是相当小的编辑,但写入通常意味着需要再次读取、编辑和保存数据。 - Erik S
8
通常情况下,你要做与这里建议的相反的事情。通常需要同步提交读取操作,因为你通常需要在返回给调用方之前获取结果。可以异步执行写入操作,因为调用方只关心从外部可观察到的状态是否与数据已写入而保持一致,这是因为在队列串行化后,没有读取操作能够继续执行直到写入完成。但无法处理多个读取者,如注意事项所述。 - Ken Thomases
同时,dispatch_barrier_async()也可能会最终出现死锁,就像这个例子:https://dev59.com/Fpbfa4cB1Zd3GeqPohc3 - Olof_t

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接