6

In Objective C I'm using a NSMutableArray instance from various thread and I'm using @synchronized to make it thread safe. currently all my acces to this array are protected with a @synchronized block, even objectAtIndex: method. Nevertheless I wonder which methods call really need to be protected with @synchronized. do I need to protect read access ?

What would happens if 'ObjectAtIndex' is not protected and called at the same time that 'removeObject' ?

If all methods are protected by a @synchronized what about performance? (I'writing a tcp/udp game server and really don't want to overprotect these array if it would decrease perf or generate locks).

for example I suppose that the 'containsObject:' method will enumerate to find the object and that I should avoid a concurent call to 'removeObject:' in another thread.

Perhaps a good solution would be to have too different locks (for read and write access)...

Help and suggestion are welcome !

Thanks a lot.

Please find a sample code below to illustrate :

@interface TestClass : NSObject
{
    NSMutableArray * array;
}

@end

@implementation TestClass

- (id)init
{
    self = [super init];
    if (self)
    {
        array = [NSMutableArray array];
    }
    return self;
}

-(id)objectAtIndex:(NSUInteger)index
{
    @synchronized(array) **// IS IT USEFUL OR NOT ??**
    {
        return [array objectAtIndex:index];
    }
}

-(void)removeObject:(id)object
{
    @synchronized(array)
    {
        [array removeObject:object];
    }
}

-(void)compute
{
    @synchronized(array)
    {
        for (id object in array)
        {
            [object compute];
        }
    }
}

@end
4

2 回答 2

5

是的,您必须同步读取访问以防止它们与突变同时发生。不过,读取访问可以安全地与其他读取访问同时运行。

如果您有多个读者,那么值得研究读写锁定方案。您可以使用 pthread 读写锁(即pthread_rwlock_...())。

或者,您可以在 OS X 10.7+ 和 iOS 5+ 上使用带有“屏障”例程的 GCD。创建一个私有并发队列。以正常方式(例如)向它提交所有读取操作dispatch_sync()。使用屏障例程向其提交变异操作,例如dispatch_barrier_async(). (它可以是异步的,因为在继续之前你一般不需要知道突变已经完成。你只需要知道在你提交突变之后提交的所有读取都会看到突变的结果,并且屏障保证了这一点。 )

如果您可以访问WWDC 2011 会议视频 Session 210 - Mastering Grand Central Dispatch,您可以了解更多信息。

于 2013-06-15T01:29:35.183 回答
0

您需要意识到,您所做的实际上并没有多大帮助。例如,如果您的数组有 10 个元素并且您调用 [myObject objectAtIndex:9] 而另一个线程调用 [myObject removeObject:someObject],那么第一个调用访问的数组元素可能不再存在并引发异常.

如果其他线程可以删除或插入对象,objectAtIndex 就不是很有用。

于 2014-02-18T23:44:06.503 回答