核心数据多线程问题

Posted

技术标签:

【中文标题】核心数据多线程问题【英文标题】:Core data multithreading issues 【发布时间】:2019-09-25 14:41:57 【问题描述】:

我已经在多线程环境中实现了核心数据,我对此有一些疑问和问题,我在下面列出:-

    几个博客和 SO 答案说你应该有一个 NSPersistentStoreCoordinator(PSC) 但根据我的理解,“PSC”应该等于 ManagedObjectModel 的数量。如果我错了,请纠正我。

    根据文档,ManagedObjectContext 对象应该等于我们为在特定模型中执行活动而创建的线程数。令我惊讶的是,我使用了来自不同线程的单个 ManagedObjectContext 对象并同时执行获取操作而没有任何崩溃,请找到以下代码:-

    我从不同的线程调用下面的函数,并确保只创建一个 MOC 实例。请清除我上面所有的疑惑

func fetchUserDetail(productId : Int) -> User_Details?  
    
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "User_Details")
    do 
        fetchRequest.predicate = NSPredicate(format: "product_id == %d", productId)
        
        let results:[User_Details]? = try (singleinstancemanagedObjectContext.fetch(fetchRequest) as? [User_Details])
        
        if let results = results 
            ..... logic .....
        
     catch let error as NSError 
    
    return nil
    

【问题讨论】:

【参考方案1】:

    “NSPersistentStoreCoordinator”只能处理一个 NSManagedObjectModel。你就在这里。但是拥有多个“NSPersistentStoreCoordinator”需要多个“NSManagedObjectModel”(.xcdatamodeld 文件)。这种情况非常罕见。

    并发崩溃本质上是难以捉摸的。它们仅在多个线程以纳秒精度同时访问相同数据时发生。当数百名用户使用该应用程序时,通常会在生产环境中出现这些难以调试的错误。您想对用户说的最后一件事是我们丢失了您的所有数据(无论是损坏还是崩溃)。所以你最好听听这里的文档。我们犯了同样的错误,在我们的一个旧应用程序的不同线程之间传递 NSManagedObjects 并付出了代价。重构代码花了很长时间。最后来自核心数据编程指南link。

NSPrivateQueueConcurrencyType 配置创建自己的队列 在初始化时,只能在该队列上使用。因为 queue 是私有的,在 NSManagedObjectContext 实例内部, 它只能通过 performBlock: 和 performBlockAndWait:方法。

这是同一页面的另一个,

NSManagedObject 实例不打算在 排队。这样做可能会导致数据损坏和终止 的应用程序。需要移交托管对象时 从一个队列到另一个队列的引用,必须通过 NSManagedObjectID 实例。

【讨论】:

如果我们使用不同的线程访问模型,最好的做法是每次创建一个 NSManagedObjectContext 或创建一个 NSManagedObjectContext 然后使用 NSPrivateQueueConcurrencyType 处理并发。

以上是关于核心数据多线程问题的主要内容,如果未能解决你的问题,请参考以下文章

多线程违规核心数据

核心数据多线程[关闭]

核心数据多线程违规

核心数据多线程:代码示例

iPhone 核心数据和多线程

多线程核心数据 - NSManagedObject 无效