在读取时改变数组,而不是枚举 [英] Mutating array while reading, not enumerating

查看:180
本文介绍了在读取时改变数组,而不是枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我通过GCD访问一个 NSMutableArray 有两个不同的线程,一个是基于可变数组创建一个新的数组,而另一个线程从数组中删除记录,我应该期望这是一个问题吗?也就是说,不应该复制,我认为只是读取数组,只是得到什么发生在数组中的那一刻?我不是枚举在任何一个线程中的数组,但它仍然崩溃。

If I have two different threads via GCD accessing an NSMutableArray and one is merely creating a new array based off the mutable array while the other thread is deleting records from the array, should I expect this to be a problem? That is, shouldn't the copy, which I presume is merely "reading" the array, just get whatever happens to be in the array at that moment? I am not enumerating the array in either thread, but it is still crashing. As soon as I remove the read routine, it works fine.

这里是读取:

  dispatch_async(saveQueue, ^{

    NSDictionary*tempstocks=[NSDictionary dictionaryWithDictionary:self.data];

它在此线程上崩溃: ***由于未捕获异常而终止应用程序'NSInvalidArgumentException',reason:'*** - [__ NSPlaceholderDictionary initWithObjects:forKeys:count:]:尝试从对象插入nil对象[9]'

[self.data removeObjectForKey:item];

我知道你枚举时不能变异,但是我认为在变异时可以读取,你可能不知道你得到了哪个版本的变异对象,但我不会可能 dictionaryWithDictionary 方法正在执行一个首先看到X对象的操作,但是在例程完成时它包含XY对象,因此当它运行 dictionaryWithDictionary 时,它不会捕获整个 self.data 字典而不是枚举 self.data 这本质上与枚举时的突变一样的问题?

I know you cannot mutate while enumerating, but I'd think it would be okay to read while mutating, you might not know which version of the mutated object you get, but I wouldn't think this is a problem, but clearly it is. Perhaps the dictionaryWithDictionary method is performing an operation that first sees X objects but by the time the routine is done it contains X-Y objects, thus it is not "capturing" the entire self.data dictionary in one snap when it runs dictionaryWithDictionary and is instead enumerating over self.data which would essentially be the same problem as mutation while enumeration?

推荐答案

我想你可能使用GCD创建三个不同的队列:一个用于保存,第二个用于其他,最后一个使用 NSMutableArray p>

I guess that you might create three different queues using GCD: one for save, second one for something else and last one to operate with NSMutableArray.

dispatch_async(saveQueue, ^{
    dispatch_barrier_async(_queue, ^{
            NSDictionary*tempstocks=[NSDictionary dictionaryWithDictionary:self.data];
        });
});

dispatch_async(anotherQueue, ^{
    dispatch_barrier_async(_queue, ^{
            [self.data removeObjectForKey:item];
        });
});

这是 @synchronize ,但使用GCD。

It's like @synchronize but using GCD.

更多信息: GCD Reference / dispatch_barrier_async http://www.mikeash.com/pyblog/friday-qa-2011-10-14-whats-new-in- gcd.html

EDIT

性能测试,以了解哪种方式更快:

I have made a couple of performance test in order to understand which of the way is faster:

- (void)usingSynchronized
{
    dispatch_queue_t writeQyeue = dispatch_queue_create("com.tikhop.writeQyeue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(writeQyeue, ^{
        for(size_t i=0; i<10000; i++)
            @synchronized (arr) {
                [arr replaceObjectAtIndex:0 withObject:[NSNumber numberWithInt:1]];
                [arr replaceObjectAtIndex:0 withObject:[NSNumber numberWithInt:2]];
                [arr replaceObjectAtIndex:0 withObject:[NSNumber numberWithInt:3]];
                [arr replaceObjectAtIndex:0 withObject:[NSNumber numberWithInt:4]];
            }
    });
}

- (void)usingGCD
{
    dispatch_queue_t writeQyeue = dispatch_queue_create("com.tikhop.writeQyeue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(writeQyeue, ^{
        for(size_t i=0; i<10000; i++)
            dispatch_barrier_async(_queue, ^{
                [arr replaceObjectAtIndex:0 withObject:[NSNumber numberWithInt:5]];
                [arr replaceObjectAtIndex:0 withObject:[NSNumber numberWithInt:6]];
                [arr replaceObjectAtIndex:0 withObject:[NSNumber numberWithInt:7]];
                [arr replaceObjectAtIndex:0 withObject:[NSNumber numberWithInt:8]];
            });
    });
}

arr = [NSMutableArray arrayWithCapacity:1];
[arr addObject:@(0)];

[self usingSynchronized];
[self usingGCD];

我得到以下结果:

I got the following result:

这篇关于在读取时改变数组,而不是枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆