CoreData 是啥意思不是线程安全的?

Posted

技术标签:

【中文标题】CoreData 是啥意思不是线程安全的?【英文标题】:What is meant by CoreData is not thread safe?CoreData 是什么意思不是线程安全的? 【发布时间】:2010-12-28 11:04:07 【问题描述】:

在Obj-C中,简单来说是什么意思; “CoreData 不是线程安全的”

或者一般来说什么是“非线程安全”?

【问题讨论】:

【参考方案1】:

@d11wtq 的回答是正确的只有在编写自己的代码或设计自己的 API 时

在使用一组 API 时这是完全错误的,而在使用 Core Data 时则完全错误。

在使用 Mac OS X 和 ios 的环境中,必须始终在使用系统 API 的环境中考虑线程安全。即使使用 NSArray 也意味着您正在使用系统 API。

或者一般来说什么是“非线程” 安全吗?

非线程安全 API 是您无法同时从多个线程与 API 交互的 API。可能还存在最常涉及主线程的其他限制。例如,几乎所有的绘图操作都必须发生在 Mac OS X 和 iOS 的主线程上。

Apple 文档假定线程安全是例外情况。也就是说,只有在文档明确声明线程安全的情况下,API 才是线程安全的。如果没有提到线程安全,则必须假定 API 不是线程安全的。

在 Obj-C 中,简单是什么意思 条款; “CoreData 不是线程安全的”

这种说法并不完全正确,但它是一个安全的假设。

在Core Data的情况下,线程交互行为是extremely well documented。

简而言之,API 的某些部分是线程安全的(例如存储协调器),而某些部分显然不是线程安全的。虽然 MOC 提供了锁定和解锁方法,但您可以也使用外部锁定。但是不要。它的效率会更低,也更脆弱;明显如此。一般来说,也不要使用内部锁定。 CoreData 针对每个线程/队列有一个上下文进行了优化。

(根据 TC 的反馈修复了答案。谢谢。)

【讨论】:

NSArray 并没有在developer.apple.com/library/mac/#documentation/Cocoa/Reference/… 的类文档中明确说它至少是线程安全的,但是使用带有 NSLock 的 NSMutableArray 来保护多个线程对其的访问是很常见的。那么这不是“安全”的用法吗? NSArray 是边界情况; 技术上 再多的锁定也不会使它成为线程安全的。 实际上实现被隔离到锁封装“足够安全”的程度。但是,问题是您必须确保该数组上的每个 方法调用都在您的锁之后;例如,您不能让数组转义到框架代码中。 有趣的是,“线程”一词并没有出现在“集合编程指南”(developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/…)中,而“安全”只出现了一次,并且正在谈论枚举和在枚举期间修改集合(不安全)。 啊,关于不让 NSArray 实例逃逸到框架代码中的要点是一个优秀,而且我确信我已经看到代码没有考虑到这一点。跨度> 我们都对 NSArray 完全错误,顺便说一句。 developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/… NSArray 被特别列为线程安全的(这在 NSArray 的历史上相对较新)。如果可以的话,我会删除我的评论。 :)【参考方案2】:

更新 |请参阅@bbum 的回答。我接受我的回答有缺陷并且@bbum 是正确的。

如果某些内容被描述为“非线程安全”,则意味着没有采取任何特殊预防措施来确保在两个单独的线程同时尝试使用它时它不会崩溃。通常,要被多个线程使用的代码需要显式锁定(或@synchronize 块)围绕代码的各个方面。特别是,任何将被修改的对象/变量几乎肯定会导致崩溃,如果两个线程碰巧同时写入它(因为它们将写入相同的内存地址)。类似地,如果一个线程正在读取一个变量而另一个线程正在写入它,则会返回垃圾并且程序可能会崩溃。

使用@synchronizedNSLock 或 POSIX 互斥锁等可确保在任何给定时间只有一个线程可以执行特定的代码块。其他线程被阻塞,必须等到锁被释放。使用锁对性能有轻微影响(当然还有一些开发开销必须考虑它们),所以代码经常明确声明它不是线程安全的,让你,代码的采用者,自己根据需要放置锁(或将非线程安全的执行限制为单个线程)。

有关线程和线程安全的更多信息,请参阅 Apple 文档:

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocThreading.html#//apple_ref/doc/uid/TP30001163-CH19-BCIIGGHG

【讨论】:

使用 @synchronized、NSLock 或 POSIX 互斥锁等,确保在任何给定时间只有一个线程可以执行特定的代码块。 在问题的上下文中这是完全错误的。您不能使用任何数量的锁定来确保线程不安全的 API 成为线程安全的! 问题,更具体地说,是其中任何一个都只能确保 that 块一次只能在一个线程上运行。它不保证任何可能使用不安全 API 的 other 块。如果你的程序的两个不同部分——或者你的程序和你使用的另一个 API 的实现——都访问了不安全的 API,那么无论你放多少锁都会发生不好的事情。 谢谢大家,我确实在这里学到了一些东西。 @hmthur 应该接受 @bbum 的回答。

以上是关于CoreData 是啥意思不是线程安全的?的主要内容,如果未能解决你的问题,请参考以下文章

PHP中的线程安全或非线程安全是啥?

CoreData 是不是可以在另一个上下文/后台任务中从一个上下文/线程安全地使用 NSManagedObject

“safety”是啥意思?

CoreData多线程安全

CoreData和SQLite多线程访问时的线程安全问题

线程安全Thread safety是什么意思?MT-Unsafe