【问题标题】:NSMutableArray thread safetyNSMutableArray 线程安全
【发布时间】:2014-01-15 14:07:26
【问题描述】:

在我的应用程序中,我正在从多个线程访问和更改一个可变数组。一开始,当我尝试使用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 这种方法,但没有运气。我做错了什么以及如何解决这个问题?

【问题讨论】:

  • 您是否也在同步对[NSMutableArray count] 的访问(以及对阵列的所有其他访问)?
  • 是的,所有使用的方法:count、removeObjectAtIndex、addObject 等。
  • 我编辑了问题并添加了整个课程代码

标签: ios objective-c thread-safety nsmutablearray


【解决方案1】:

我认为这个解决方案很糟糕。考虑一下:

  1. 线程 #1 调用 count 并被告知数组中有 4 个对象。
  2. 数组未同步。
  3. 线程#2 调用数组上的removeObjectAtIndex:2
  4. 数组未同步。
  5. 线程#1 调用objectAtIndex:3 出现错误。

相反,您需要一个更高级别的锁定机制,其中在第 1 步和第 5 步都锁定在数组周围,并且线程 #2 无法在这些步骤之间删除对象。

【讨论】:

  • @Euroboy 这是一个更好的 SO 问题:stackoverflow.com/questions/17091389/…
  • 是的,我以前见过这个问题……我从那里得到了启发。但是我也尝试了 GCD 方法,但问题仍然存在......我很困惑 :(
  • 我把这个方法留给了一个类,直接用@synchronized给我的NSMutableArray,现在一切正常了。
【解决方案2】:

您需要保护(使用@synchronized)基本上所有数组的使用。目前,您只能防止多个线程同时从数组中取出对象。但是对于您描述的并发修改和突变的场景,您没有任何保护。

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

【讨论】:

    猜你喜欢
    • 2012-08-19
    • 1970-01-01
    • 2016-07-27
    • 2022-11-21
    • 1970-01-01
    • 2021-07-12
    • 2011-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多