2012-08-09 44 views
5

我有一个类,使用一个可变数组,经过大量的读取(新项目到达)后修改一次。避免复制NSMutableArray读取多线程写入

问题是,当时代来突变数组,读取不断来。

目前以避免此问题每次读的东西它这样做在复印时间:

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

副本将成为真正昂贵,尤其是当有没有必要(所有那些时候,数组是没有被突变)。

如何锁定数组,以便在突变时延迟对数组的访问?

+0

为什么你不把这个数组作为你的类的属性,并且在声明期间使它成为原子,编译器会处理线程之间的任何类型的同步。 – kidsid49 2012-10-21 18:30:14

回答

9

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

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

+1

正确完成,这允许并行读取器和非阻止作者。这绝对是今天的首选解决方案。 – 2012-08-09 19:34:48

2

在这种情况下,您会考虑使用读/写锁。可可不提供它们,但pthread_rwlock_t可用于pthreads接口 - 在pthread.h中声明。请注意,这将比@synchronized更有效率(用于您的使用),甚至是简单的锁定。

5

最简单的方法是使用@synchronized,像这样:

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

编辑:如果不使用ARC,您可能希望保留/自动释放的对象,否则它可能会从阵列中移除(并发布)之前someMessage被称为(感谢omz这个优秀的评论)。

+0

应该指出,尽管Xcode不能识别@synchronized作为关键字,但它仍然有效。 – 2012-08-09 19:27:41

+0

如果不使用ARC,你可能想''保留'''autorelease'这个对象,否则可能会在调用someMessage之前将它从数组中移除(并释放)。 – omz 2012-08-09 19:28:00

+0

@omz非常感谢你,这是一个非常重要的评论!像这样的“小事”帮助我更全面地了解我的生活在ARC下更容易。 – dasblinkenlight 2012-08-09 19:33:21