NSMutableArray线程安全

时间:2014-01-15 14:07:27

标签: ios objective-c thread-safety nsmutablearray

在我的应用程序中,我正在访问并更改多个线程中的可变数组。在开始时,当我尝试使用objectAtIndex访问对象时崩溃了,因为索引超出范围(该索引处的对象已经从另一个线程中的数组中删除)。我在互联网上搜索了如何解决这个问题,我决定尝试这个solution。我创建了一个NSMutableArray属性的类,请参阅以下代码:

@interface SynchronizedArray()
@property (retain, atomic) NSMutableArray *array;
@end

@implementation SynchronizedArray

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

-(id)objectAtIndex:(NSUInteger)index
{
    @synchronized(_array)
    {
        return [_array objectAtIndex:index];
    }
}

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

-(void)removeObjectAtIndex:(NSUInteger)index
{
    @synchronized(_array)
    {
        [_array removeObjectAtIndex:index];
    }
}

-(void)addObject:(id)object
{
    @synchronized(_array)
    {
        [_array addObject:object];
    }
}

- (NSUInteger)count
{
    @synchronized(_array)
    {
        return [_array count];
    }
}

-(void)removeAllObjects
{
    @synchronized(_array)
    {
        [_array removeAllObjects];
    }
}

-(id)copy
{
    @synchronized(_array)
    {
        return [_array copy];
    }
}

我使用这个类而不是旧的可变数组,但是这个应用程序仍然在这一行崩溃:return [_array objectAtIndex:index];我用NSLock尝试了这种方法,但没有运气。我做错了什么以及如何解决这个问题?

2 个答案:

答案 0 :(得分:7)

我相信这个解决方案很差。考虑一下:

  1. 线程#1调用count并告知阵列中有4个对象。
  2. 数组未同步。
  3. 线程#2调用阵列上的removeObjectAtIndex:2
  4. 数组未同步。
  5. 线程#1调用objectAtIndex:3并发生错误。
  6. 相反,您需要一个更高级别的锁定机制,其中锁定在步骤1和5的数组周围,而线程#2无法在这些步骤之间删除对象。

答案 1 :(得分:4)

您需要保护(使用@synchronized)基本上所有数组的使用。目前,您只能阻止多个线程同时从数组中获取对象。但是你没有保护所描述的并发修改和变异的情况。

问问自己为什么要在多个线程上修改数组 - 你应该这样做还是只使用一个线程?使用不同的数组实现或使用总是切换到主线程以进行请求修改的包装类可能更容易。