【问题标题】:iOS concurrency: NSOperationQueue and ARC issueiOS 并发:NSOperationQueue 和 ARC 问题
【发布时间】:2015-03-01 10:20:05
【问题描述】:

我目前正在实现一个多线程应用程序,但遇到了一个奇怪的竞争条件(导致 ARC 问题:对象 0x7f8bcbd6a1c0 错误:未分配指针被释放)。

该应用程序创建多个 NSOperations,每个 NSOperations 都在下载和处理信息。就像在这些 NSOperations 中的每一个中一样,可能会发生错误(例如,Web 服务不可用),我想向上传播错误以便我可以处理它。但是,我似乎遇到了竞争条件,操作尝试访问无效内存。

显示内存访问问题的简单示例如下:

- (void) createError: (NSError**) err {
    *err = [[NSError alloc] initWithDomain:@"Test" code:12345 userInfo:nil];
}

- (void)viewDidLoad {
    [super viewDidLoad];

    __block NSError *globalError = nil;

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    NSOperation *op = nil;
    for (int i=0; i<10; i++) {
        op = [NSBlockOperation blockOperationWithBlock:^{
            NSError *err = nil;
            [self createError:&err];

            // This loop increases the chance to get the race condition
            for (int j=0; j<10000;j++) {
                @synchronized(globalError) {
                      globalError = err;
                }
            }
        }];
        [queue addOperation:op];
    }

    [queue waitUntilAllOperationsAreFinished];

    if (globalError) {
        NSLog(@"An error occured in at least one of the operations");
    }
}

每当我运行这个程序时,我都会遇到异常。主要是对象 0x7fc0b860e860 的错误:未分配指针被释放,但是,有时我在调试器中也遇到了 EXC_BAD_ACCESS (code=EXC_I386_GPFLT) 中断。

我添加了超过 10000 次迭代的 for 循环,只是为了增加竞争条件发生的机会。如果我离开它,错误只会在极少数情况下发生(但仍然必须修复,显然我在这里做错了)。

【问题讨论】:

  • 我想我找到了。我在 nil 上同步,它实际上不执行任何同步。

标签: objective-c multithreading concurrency automatic-ref-counting nsoperationqueue


【解决方案1】:

@synchronized 指令使用您传递的对象来控制同步,因此,正如您所注意到的,您正在尝试在 nil 上进行同步。即使不是nil@synchronized 指令所引用的对象每次都是不同的对象,很大程度上挫败了同步尝试。

最简单的更改是改用@synchronized(self)。或者,创建一个NSLock 对象,然后在访问globalError 时创建lockunlock。或者,如果这是一个高需求情况,请使用 GCD 队列(串行队列或读写器模式)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    相关资源
    最近更新 更多