【问题标题】:Is the @NSManaged property thread safe?@NSManaged 属性线程安全吗?
【发布时间】:2021-11-07 07:38:27
【问题描述】:
以案例为例:
@NSManaged public var myProperty: SomeType
func someFunc() {
concurrentNSManagedObjectContext.perform {
doSomething(with: self.myProperty)
}
}
如果是,最佳做法是什么?
【问题讨论】:
标签:
ios
swift
core-data
concurrency
nsmanagedobject
【解决方案1】:
使用@NSManaged 对线程安全没有影响。它帮助 Core Data 管理属性,但不会为线程或其他任何东西保持属性安全。
如果doSomething 函数与Core Data 相关,那么使用perform 会很好,因为perform 和performAndWait 是Core Data 管理线程安全的方式。访问perform 或performAndWait 内的属性是安全的;在这些函数之外访问它通常是不安全的。
上述唯一的例外是,如果您的托管对象上下文使用主队列并发(例如,如果您使用 NSPersistentContainer 并且上下文是 viewContext 属性)和您确定您的代码在主队列上运行,那么您不需要使用perform 或performAndWait。在这种情况下使用它们还不错,但也没有必要。
【解决方案2】:
到目前为止,至少在 Apple 平台中的“线程安全”解决了两件事;读写。 NSManaged 对象目前不能防止两者混合使用。如果其他线程在突变时正在读取 myProperty,则 func doSomething(...) 将引发异常。突变可以在串行线程上完成,但是线程安全比这更复杂。 someFunc() 由第一个调用者调用;如果该调用者来自并发线程,则无法保证顺序。例如,如果 myProperty 是 Int 类型,并且我从 200 个线程并发调用 someFunc,则最后一个线程可能是 0,而 someFunc 可能是 += 1。现在,如果我使 func 串行,我的最终输出是 1。所以简短的答案是取决于您要完成的工作。通常你在串行队列上是安全的,但并发需要很多计划。