GCD - 串行队列是否需要“NSLock”或内存屏障才能同步工作?

时间:2018-02-05 18:17:42

标签: objective-c grand-central-dispatch

我阅读了关于GCD队列的Apple文档,并开始想知道如果我想修改类型为.babelrc的实例成员在串行队列中不是线程安全的会发生什么?串行队列将保证我连续执行操作,但我仍然认为我需要执行NSMutableArray块或其他技术来强制内存屏障,因为据我所知,我的序列上的任务可以在不同的线程上调用队列。那是对的吗?这是一个简单的例子:

@syncrhonized

据我所知,如果我从任意线程调用成员方法,我可能会遇到内存问题?或者GCD在引擎盖下提供了一些保证,为什么我不需要强制记忆障碍?看看这些例子,我没有在任何地方找到这样的结构,但是从C ++开始,在锁定下触摸成员变量是有意义的。

2 个答案:

答案 0 :(得分:5)

如果您的队列是一个串行队列,它将一次只允许一个操作,无论它在哪个线程上运行。因此,如果在队列上发生对资源的每次访问,则不需要使用锁或信号量进一步保护该资源。实际上,可以将调度队列用作锁定机制,对于某些应用程序,它可以很好地工作。

现在,如果您的队列是并发队列,那么这是一个不同的故事,因为多个操作可以同时在并发队列上运行。但是,GCD提供dispatch_barrier_syncdispatch_barrier_async API。通过这两个函数调用启动的操作将导致队列在执行块之前等待所有其他操作完成,然后在块完成之前禁止运行任何其他操作。通过这种方式,它可以暂时使队列的行为类似于串行队列,甚至允许将并发队列用作一种锁定机制(例如,允许通过正常的dispatch_sync调用读取资源,但是通过dispatch_barrier_async进行写入。如果读取非常频繁且写入很少,则可以很好地执行。“

答案 1 :(得分:2)

串行队列数据锁,因此至少就此代码而言,不需要进一步的锁定/同步。可以使用不同线程执行相同队列的事实是一个您不应该考虑的实现细节;队列是领域的硬币。

当然,在此队列和队列之间共享数组时可能存在问题,但这是另一回事。