避免复制NSMutableArray以便使用多线程写入进行读取

时间:2012-08-09 19:23:04

标签: objective-c cocoa-touch concurrency nsmutablearray

我有一个使用可变数组的类,该数组在大量读取(新项目到达)后被修改一次。

问题在于,当数组变异时,读取会继续发生。

目前为了避免这个问题,每次它读取的内容都是通过副本完成的:

[[theArray copy] operation] //operation being indexOfObject:, objectAtIndex: objectsAtIndexes:, etc.

副本变得非常昂贵,特别是在没有必要时(所有那些时候阵列没有被变异)。

如何锁定数组以在发生变异时延迟对它的访问?

3 个答案:

答案 0 :(得分:9)

将所有数组访问放入串行调度队列。这将防止任何两个操作同时发生。请参阅“并发编程指南”中的"Eliminating Lock-based Code"

如果您可以要求iOS> = 4.3,则可以使用并发自定义队列和dispatch barriers进行变异操作。这将允许读取同时发生,但是当需要写入时,它们将被保持直到写入完成。作为屏障提交的块基本上在并发队列上串行执行 - 它将在所有先前的块完成之后才开始,在屏障块完成之前也不会开始任何后续块。 (这是Justin提到的读写锁的GCD版本。)我引导你到samples of this的无法模仿的Mike Ash。

答案 1 :(得分:5)

最简单的方法是使用@synchronized,如下所示:

-(void) accessTheArray {
    MyClass *obj;
    @synchronized(theArray) {
        obj = [theArray objectAtIndex:...];
    }
    [obj someMessage];
}

编辑:如果不使用ARC,您可能希望保留/自动释放该对象,否则可能会在调用someMessage之前将其从阵列中删除(并释放)(感谢您omz获得此优秀评论。)

答案 2 :(得分:2)

在这种情况下,您会考虑使用读/写锁。 Cocoa不提供它们,但pthread_rwlock_t在pthreads接口中可用 - 在pthread.h中声明。请注意,这比({1}}更有效(对于您的使用),甚至是普通锁定。