我有一个使用可变数组的类,该数组在大量读取(新项目到达)后被修改一次。
问题在于,当数组变异时,读取会继续发生。
目前为了避免这个问题,每次它读取的内容都是通过副本完成的:
[[theArray copy] operation] //operation being indexOfObject:, objectAtIndex: objectsAtIndexes:, etc.
副本变得非常昂贵,特别是在没有必要时(所有那些时候阵列没有被变异)。
如何锁定数组以在发生变异时延迟对它的访问?
答案 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}}更有效(对于您的使用),甚至是普通锁定。