这种方法会导致并发问题吗?

Posted

技术标签:

【中文标题】这种方法会导致并发问题吗?【英文标题】:Does this method cause concurrency problems? 【发布时间】:2011-06-01 21:10:52 【问题描述】:

我有一个带有类方法的 CoreDataUtilities 类,该类方法可以保存托管对象上下文并处理任何错误:

+ (void)saveContext:(NSManagedObjectContext*)moc 
    NSError *error = nil;
    if (moc != nil) 
        if ([moc hasChanges] && ![moc save:&error]) 
            NSLog(@"MOC save error: %@, %@", error, [error userInfo]);
         
    

我从 NSOperation 子类和后台线程调用这个方法,并传入线程/NSOperation 的 NSManagedObjectContext 实例。

我担心的是:

如果线程 A 调用了这个方法,当这个方法执行到一半时,线程 B 也会调用它。当然还有另一个 MOC。这会以任何方式干扰吗?从我的角度来看,它不会,因为这个方法只与调用线程“私有”或“拥有”的 MOC 实例通信。但是让我恼火的是,当多个线程同时执行同一段代码时,即使方法中的局部变量也会“混淆”。还是每个变量在新线程中都有自己的“上下文”,有自己的内存堆(或堆栈,就此而言)?

如果我把这个保存代码直接放到 NSOperation 子类和后台线程中会有很大的不同吗?为什么?

【问题讨论】:

【参考方案1】:

为什么不在保存操作周围放置一个@synchronize(...) 块。这将确保托管对象上下文在已保存时不会被保存。

+ (void)saveContext:(NSManagedObjectContext*)moc 
    if (moc == nil) return;

    @synchronized(moc)
    
        NSError *error = nil;
        if ([moc hasChanges] && ![moc save:&error])
            NSLog(@"MOC save error: %@, %@", error, [error userInfo]);
     

阅读here 同步。

【讨论】:

【参考方案2】:

规则是每个线程必须有自己的moc。

查看Apple's Guidelines了解更多信息。

【讨论】:

是的,每个线程都有自己的 MOC。所以如果一个线程调用 [CoreDataUtilities saveContext:myMOC] 那么会有问题吗?问题是多个线程将他们自己的 MOC 传递给这个单一的保存方法。 如果您在每个线程上都有一个 moc,则无需担心重叠的保存调用,因为在 moc 之下苹果处理并发。在 moc 上进一步同步不会有任何好处,因为它会是每个线程的不同对象

以上是关于这种方法会导致并发问题吗?的主要内容,如果未能解决你的问题,请参考以下文章

RabbitMQ:忽略 prefetch() 会导致数据并发吗?

「解决方案」SpringBoot项目中如何解决并发导致的重复提交问题

多线程并发会造成程序周期性崩溃吗?

浅谈并发性模型的测试策略

PG核心技术篇--MVCC

内存中的 SQLite 数据库可以并发扩展吗?