NSMutableArray线程安全性

3

在我的应用程序中,我从多个线程访问和更改可变数组。起初,当我尝试使用objectAtIndex访问对象时会崩溃,因为索引超出了边界(该索引处的对象已经在另一个线程中从数组中删除)。我在互联网上搜索了如何解决这个问题,并决定尝试这个解决方案。我创建了一个带有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,但仍然没有成功。我做错了什么,如何修复?


1
你也同步访问 [NSMutableArray count](以及数组的每次访问)了吗? - trojanfoe
是的,所有使用的方法:count、removeObjectAtIndex、addObject等。 - iOS Dev
我编辑了问题并添加了整个类代码。 - iOS Dev
2个回答

7
我认为这个解决方案很差。考虑以下情况:
1. 线程#1调用`count`方法,并被告知数组中有4个对象。 2. 数组未同步。 3. 线程#2在数组上调用`removeObjectAtIndex:2`方法。 4. 数组未同步。 5. 线程#1调用`objectAtIndex:3`方法,导致出错。
相反,您需要在更高的级别上使用锁定机制,在步骤1和5周围锁定数组,使得线程#2无法在这些步骤之间删除对象。

@Euroboy 这是一个更好的SO问题可以使用:https://dev59.com/PnPYa4cB1Zd3GeqPhEgZ - trojanfoe
是的,我以前见过这个问题...我从那里得到了灵感。然而,我也尝试了GCD方法,但问题仍然存在...我很困惑 :( - iOS Dev
我将方法与类分开,直接在我的NSMutableArray中使用了@synchronized,现在一切都正常工作。 - iOS Dev

4
你需要使用 @synchronized 来保护数组的所有使用。目前你只是防止多个线程同时从数组中获取对象。但是,你没有保护并发修改和变异的情况。
问问自己为什么要在多个线程上修改数组 - 你是否应该这样做,还是只使用一个线程?可能更容易使用不同的数组实现或使用包装类,始终切换到主线程来进行所需的修改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接