Ios 使用全局并发队列从两个不同的线程变异数组时不会崩溃

Ios 使用全局并发队列从两个不同的线程变异数组时不会崩溃,ios,objective-c,concurrency,concurrent-queue,Ios,Objective C,Concurrency,Concurrent Queue,在下面的代码中,我们有一个可变数组,它由两个并发队列进行变异。由于并发队列不是线程安全的,因此理想情况下,此代码应该崩溃,但执行时不会出现任何异常或崩溃 请帮助我理解这种行为。任何帮助都将不胜感激:-) @界面视图控制器() @属性(非原子,强)NSMUTABLEARRY*arr; @结束 @实现视图控制器 -(无效)viewDidLoad{ [超级视图下载]; //加载视图后,通常从nib执行任何其他设置。 self.arr=[NSMutableArray new]; } -(无效)视图显示:

在下面的代码中,我们有一个可变数组,它由两个并发队列进行变异。由于并发队列不是线程安全的,因此理想情况下,此代码应该崩溃,但执行时不会出现任何异常或崩溃

请帮助我理解这种行为。任何帮助都将不胜感激:-)

@界面视图控制器()
@属性(非原子,强)NSMUTABLEARRY*arr;
@结束
@实现视图控制器
-(无效)viewDidLoad{
[超级视图下载];
//加载视图后,通常从nib执行任何其他设置。
self.arr=[NSMutableArray new];
}
-(无效)视图显示:(BOOL)动画{
[超级视图显示:动画];
__弱类型(自我)弱自我=自我;
调度异步(调度获取全局队列(调度队列优先级默认为0)^{
对于(int i=0;i<20000;i++){
[weakSelf.arr addObject:[NSNumber numberwhithint:i]];
NSLog(@“添加%@,[weakSelf.arr lastObject]);
}
NSLog(@“最终计数%ld,[self.arr计数]);
});
[自执行选择器:@selector(removeObjects)with object:nil afterDelay:0.1];
}
-(无效)移除对象{
__弱类型(自我)弱自我=自我;
调度异步(调度获取全局队列(调度队列优先级默认为0)^{
对于(int i=0;i<1000;i++){
如果(weakSelf.arr.count>1){
[weakSelf.arr removeObjectAtIndex:0];
}
NSLog(@“删除对象”);
}
});
}
@结束

同时访问一个资源并不意味着保证崩溃。这与“运气”无关。也许您的代码在没有崩溃发生的情况下系统地运行


此外,“非线程安全”并不意味着“将崩溃”。任何故障都可能发生。

同时访问
NSMutableArray
不会明确导致崩溃,但会导致阵列损坏,从而导致应用程序因无效数据而崩溃

考虑一下您的代码的这个稍加修改的版本:

-(void)viewDidAppear:(BOOL)animated{

    [super viewDidAppear:animated];

    __weak typeof(self) weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
        for (int i = 0; i < 20000; i++) {
           NSUInteger randomIndex = arc4random_uniform([weakSelf.arr count]);
            [weakSelf.arr insertObject:[NSNumber numberWithInt:i] atIndex:randomIndex];
            NSLog(@"Added %@", weakSelf.arr[randomIndex]);
        }

        NSLog(@"Final count %ld", [self.arr count]);
    });

    [self performSelector:@selector(removeObjects) withObject:nil afterDelay:0.1];
}

-(void)removeObjects{
    __weak typeof(self) weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        for (int i = 0; i < 1000; i++) {
            if (weakSelf.arr.count > 1) {
                 NSUInteger randomIndex = arc4random_uniform([weakSelf.arr count]);
                [weakSelf.arr removeObjectAtIndex:randomIndex];
            }
            NSLog(@"Remove object");
        }
    });
}

在使用快速枚举时对数组进行变异会导致崩溃,但在这种情况下,变异甚至不必来自另一个线程;简单地在枚举循环中改变数组就会导致崩溃。

也许你只是幸运而已。我可能错了,但我不确定你的代码一定会崩溃;我想它只是不能保证不会崩溃。。。根据定义,你不能依靠比赛条件来保持一致…@NicolasMiari谢谢你的意见。我多次尝试运行此代码,但没有一次它引发异常。我不可能每次都很幸运。我试图找出各种可能有助于避免异常的可能性,如块范围,但我无法得出任何可能准确的结论。您实际在哪里分配数组
arr
为零,因此您的代码不起作用anything@Paulw11:我正在分配数组,为了简单起见,我刚才跳过了问题中的那行代码。我已编辑了我的问题,以包括分配。
-(void)viewDidAppear:(BOOL)animated{

    [super viewDidAppear:animated];

    __weak typeof(self) weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
        for (int i = 0; i < 20000; i++) {
           NSUInteger randomIndex = arc4random_uniform([weakSelf.arr count]);
            [weakSelf.arr insertObject:[NSNumber numberWithInt:i] atIndex:randomIndex];
            NSLog(@"Added %@", weakSelf.arr[randomIndex]);
        }

        NSLog(@"Final count %ld", [self.arr count]);
    });

    [self performSelector:@selector(removeObjects) withObject:nil afterDelay:0.1];
}

-(void)removeObjects{
    __weak typeof(self) weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        for (int i = 0; i < 1000; i++) {
            if (weakSelf.arr.count > 1) {
                 NSUInteger randomIndex = arc4random_uniform([weakSelf.arr count]);
                [weakSelf.arr removeObjectAtIndex:randomIndex];
            }
            NSLog(@"Remove object");
        }
    });
}
-(void)viewDidAppear:(BOOL)animated{

    [super viewDidAppear:animated];

    __weak typeof(self) weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
        for (int i = 0; i < 20000; i++) {
            @synchronized (self.arr) {

           NSUInteger randomIndex = arc4random_uniform([weakSelf.arr count]);
            [weakSelf.arr insertObject:[NSNumber numberWithInt:i] atIndex:randomIndex];
            NSLog(@"Added %@", weakSelf.arr[randomIndex]);
            }
        }

        NSLog(@"Final count %ld", [self.arr count]);
    });

    [self performSelector:@selector(removeObjects) withObject:nil afterDelay:0.1];
}

-(void)removeObjects{
    __weak typeof(self) weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        for (int i = 0; i < 1000; i++) {
            if (weakSelf.arr.count > 1) {
                @synchronized (self.arr) {

                 NSUInteger randomIndex = arc4random_uniform([weakSelf.arr count]);
                [weakSelf.arr removeObjectAtIndex:randomIndex];
                }
            }
            NSLog(@"Remove object");
        }
    });
}