基础框架(Fondation Framework)的线程安全

基础框架(Fondation Framework)的线程安全

有一种误解,认为基础框架(Foundation framework)是线程安全的,而Application Kit是非线程安全的。不幸的是,这是一个总的概括,从而造成一点误导。每个框架都包含了线程安全部分和非线程安全部分。以下部分介绍Foundation framework里面的线程安全部分。

 

线程安全的类和函数

下面这些类和函数通常被认为是线程安全的。你可以在多个线程里面使用它们的同一个实例,而无需获取一个锁。

 

非线程安全类

以下这些类和函数通常被认为是非线程安全的。在大部分情况下,你可以在任何线程里面使用这些类,只要你在同一个时间只在一个线程里面使用它们。参考这些类对于的额外详细信息的文档。

 

注意,尽管NSSerializer,NSArchiver,NSCoder和NSEnumerator对象本身是线程安全的,但是它们被放置这这里是因为当它们封装的对象被使用的时候,更改这些对象数据是不安全的。比如,在归档情况下,修改被归档的对象是不安全的。对于一个枚举,任何线程修改枚举的集合都是不安全的。

 

只能用于主线程的类

以下的类必须只能在应用的主线程类使用。

  • NSAppleScript

 

可变 vs 不可变

不可变对象通常是线程安全的。一旦你创建了它们,你可以把它们安全的在线程间传递。当前,在使用不可变对象时,你还应该记得正确使用引用计数。如果不适当的释放了一个你没有引用的对象,你在随后有可能造成一个异常。

可变对象通常是非线程安全的。为了在多线程应用里面使用可变对象,应用应该使用锁来同步访问它们(关于更多信息,参见“原子操作”部分)。通常情况下,集合类(比如,NSMutableArray,NSMutableDictionary)是考虑多变时是非线程安全的。这意味着,如果一个或多个线程同时改变一个数组,将会发生问题。你应该在线程读取和写入它们的地方使用锁包围着。

即使一个方法要求返回一个不可变对象,你不应该简单的假设返回的对象就是不可变的。依赖于方法的实现,返回的对象有可能是可变的或着不可变的。比如,一个返回类型是NSString的方法有可能实际上由于它的实现返回了一个NSMutableString。如果你想要确保对象是不可变的,你应该使用不可变的拷贝。

 

可重入性

可重入性是可以让同一对象或者不同对象上一个操作“调用”其他操作成为可能。保持和释放对象就是一个有可能被忽视的”调用”的例子。

以下列表列出了Foundation framework的部分显式的可重入对象。所有其他类可能是或可能不是可重入的,或者它们将来有可能是可重入的。对于可重入性的一个完整的分析是不可能完成的,而且该列表将会是无穷尽的。

 

类的初始化

Objective-C的运行时系统在类收到其他任何消息之前给它发送一个initialize消息。这可以让类有机会在它被使用前设置它的运行时环境。在一个多线程应用里面,运行时保证仅有一个线程(该线程恰好发送第一条消息给类)执行initialized方法,第二个线程阻塞直到第一个线程的initialize方法执行完成。在此期间,第一个线程可以继续调用其他类上的方法。该initialize方法不应该依赖于第二个线程对这个类的调用。如果不是这样的话,两个线程将会造成死锁。

 

自动释放池(Autorelease Pools)

每个线程都维护它自己的NSAutoreleasePool的栈对象。Cocoa希望在每个当前线程的栈里面有一个可用的自动释放池。如果一个自动释放池不可用,对象将不会给释放,从而造成内存泄露。对于Application Kit的主线程通常它会自动创建并消耗一个自动释放池,但是辅助线程(和其他只有Foundationd的程序)在使用Cocoa前必须自己手工创建。如果你的线程是长时间运行的,那么有可能潜在产生很多自动释放的对象,你应该周期性的销毁它们并创建自动释放池(就像Application Kit对主线程那样)。否则,自动释放对象将会积累并造成内存大量占用。如果你的脱离线程没有使用Cocoa,你不需要创建一个自动释放池。

 

 

Run Loops

每个线程都有一个或多个run loop。然而每个run loop和每个线程都有它自己的输入模式来决定run loop运行的释放监听那些输入源。输入模式定义在一个run loop上面,不会影响定义在其他run loop的输入模式,即使它们的名字相同。

如果你的线程是基于Application Kti的话,主线程的run loop会自动运行,但是辅助线程(和只有Foundation的应用)必须自己启动它们的run loop。如果一个脱离线程没有进入run loop,那么线程在完成它们的方法执行后会立即退出。

尽管外表显式可能是线程安全的,但是NSRunLoop类是非线程安全的。你只能在拥有它们的线程里面调用它实例的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值