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

Die*_*res 5 concurrency cocoa-touch objective-c nsmutablearray

我有一个类,它使用一个可变数组,在大量读取(新项到达)后修改一次.

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

目前为了避免这个问题,每次它读取的内容都会在副本上执行此操作:

[[theArray copy] operation] //operation being indexOfObject:, objectAtIndex: objectsAtIndexes:, etc.
Run Code Online (Sandbox Code Playgroud)

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

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

Jos*_*ell 9

将所有数组访问放入串行调度队列.这将防止任何两个操作同时发生.请参阅"并发编程指南"中的"消除基于锁的代码".

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


das*_*ght 5

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

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

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