从不同线程访问只读对象的想法 [英] Thoughts in accessing read only objects from different threads

查看:76
本文介绍了从不同线程访问只读对象的想法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于我之前在SO中进行的讨论(请参阅

Based on a previous discussion I had in SO (see Doubts on concurrency with objects that can be used multiple times like formatters), here I'm asking a more theoretical question about objects that during the application lifetime are created once (and never modified, hence read-only) and they can be accessed from different threads. A simple use case it's the Core Data one. Formatters can be used in different threads (main thread, importing thread, etc.).

NSFormatter创建起来非常昂贵.基于此,它们可以创建一次,然后再使用.以下是一个可以遵循的典型模式(在 NSFormatter 文章中也用@mattt突出显示了).

NSFormatters, for example, are extremely expensive to create. Based on that they can created once and then reused. A typical pattern that can be follow (also highlighted by @mattt in NSFormatter article) is the following.

+ (NSNumberFormatter *)numberFormatter {
    static NSNumberFormatter *_numberFormatter = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _numberFormatter = [[NSNumberFormatter alloc] init];
        [_numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
    });

    return _numberFormatter;
}

即使我确定这是一个很好的遵循方法(创建了一种只读/不可变对象),格式化程序也不是线程安全的,因此以线程安全的方式使用它们可能会很危险.我在在不同线程中使用NSDateFormatter时崩溃了.作者注意到可能发生崩溃的地方.

Even if I'm sure that is a very good approach to follow (a sort of read-only/immutable object is created), formatters are not thread safe and so using them in a thread safe manner could be dangerous. I found a discussion on the argument in NSDateFormatter crashes when used from different threads where the author has noticed that a crash could happen.

NSDateFormatters不是线程安全的;有一个后台线程 尝试同时使用相同的格式化程序(因此 随机性.)

NSDateFormatters are not thread safe; there was a background thread attempting to use the same formatter at the same time (hence the randomness).

那么,从不同的线程访问格式化程序可能是什么问题?有没有遵循的安全模式?

So, what could be the problem in accessing a formatter from different threads? Any secure pattern to follow?

推荐答案

格式化程序的具体答案:

Specific answer for formatters:

在iOS 7/OSX 10.9之前,即使对格式化程序的只读访问也不是线程安全的. ICU会响应请求执行大量的延迟计算,如果同时执行,可能会崩溃或产生不正确的结果.

Prior to iOS 7/OSX 10.9, even read-only access to formatters was not thread-safe. ICU has a ton of lazy computation that it does in response to requests, and that can crash or produce incorrect results if done concurrently.

在iOS 7/OSX 10.9中,NSDateFormatterNSNumberFormatter在内部使用锁来序列化对基础ICU代码的访问,从而避免了此问题.

In iOS 7/OSX 10.9, NSDateFormatter and NSNumberFormatter use locks internally to serialize access to the underlying ICU code, preventing this issue.

一般答案:

真正的访问/不可变对象通常确实是线程安全的,但是很难分辨出哪些东西实际上是内部不可变的,而哪些只是向外部世界提供了不可变的接口.

Real-only access/immutable objects are indeed generally thread-safe, but it's difficult-to-impossible to tell which things actually are internally immutable, and which ones are merely presenting an immutable interface to the outside world.

在您自己的代码中,您可以知道这一点.使用其他人的课程时,您必须依靠他们的文档来证明如何安全地使用他们的课程.

In your own code, you can know this. When using other people's classes, you'll have to rely on what they document about how to use their classes safely.

(编辑,因为要求提供对格式化程序的序列化访问的示例)

(edit, since an example of serializing access to formatters was requested)

// 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) });

这篇关于从不同线程访问只读对象的想法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆