Lor*_*o B 4 multithreading objective-c thread-safety nsformatter
基于我之前在SO中的讨论(请参阅对可以像格式化程序一样多次使用的对象的并发性的疑问),这里我要求一个关于在应用程序生命周期中创建一次的对象的更多理论问题(并且从未修改过,因此只读)并且可以从不同的线程访问它们.一个简单的用例是核心数据.Formatters可用于不同的线程(主线程,导入线程等).
NSFormatter例如,创建起来非常昂贵.基于此,他们可以创建一次然后重用.可以遵循的典型模式(在NSFormatter文章中也由@mattt强调)如下.
+ (NSNumberFormatter *)numberFormatter {
static NSNumberFormatter *_numberFormatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_numberFormatter = [[NSNumberFormatter alloc] init];
[_numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
});
return _numberFormatter;
}
Run Code Online (Sandbox Code Playgroud)
即使我确定这是一个非常好的方法(创建了一种只读/不可变对象),格式化程序也不是线程安全的,因此以线程安全的方式使用它们可能很危险.我发现有关NSDateFormatter崩溃的参数的讨论,当从不同的线程使用时,作者注意到可能发生崩溃.
NSDateFormatters不是线程安全的; 有一个后台线程试图同时使用相同的格式化程序(因此随机性).
那么,从不同的线程访问格式化程序可能会出现什么问题呢?是否有任何安全模式?
格式化程序的具体答案:
在iOS 7/OSX 10.9之前,即使是对格式化程序的只读访问也不是线程安全的.ICU有大量的懒惰计算,它响应请求,并且如果同时完成,可能会崩溃或产生不正确的结果.
在iOS 7/OSX 10.9中,NSDateFormatter并在NSNumberFormatter内部使用锁来序列化对底层ICU代码的访问,从而防止出现此问题.
一般答案:
真正的访问/不可变对象确实通常是线程安全的,但很难不可能分辨出哪些内容实际上是不可变的,哪些只是向外界呈现一个不可变的接口.
在您自己的代码中,您可以知道这一点.当使用其他人的课程时,您将不得不依赖他们所记录的关于如何安全地使用他们的课程的内容.
(编辑,因为要求序列化访问格式化程序的示例)
// in the dispatch_once where you create the formatter
dispatch_queue_t formatterQueue = dispatch_queue_create("date formatter queue", 0);
// where you use the formatter
dispatch_sync(formatterQueue, ^{ (do whatever you wanted to do with the formatter) });
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
245 次 |
| 最近记录: |