Objective c NSSortDescriptor线程安全吗?

Objective c NSSortDescriptor线程安全吗?,objective-c,thread-safety,Objective C,Thread Safety,我有一个类的setter,我想在设置时对输入进行排序(调用的频率不够高,成本也可以),我想让它快一点,我会创建一个静态NSSortDescriptor来使用,因为排序参数总是相同的 不过setter是原子的,我想知道在@synchronized块之外的多个线程中使用相同的NSSortDescriptor实例是否安全(因为我在进入@synchronized块之前要对传入数组进行排序)。以下代码是线程安全的吗?或者这是太多的过早优化 - (void) setMyArray:(NSArray*)new

我有一个类的setter,我想在设置时对输入进行排序(调用的频率不够高,成本也可以),我想让它快一点,我会创建一个静态NSSortDescriptor来使用,因为排序参数总是相同的

不过setter是原子的,我想知道在@synchronized块之外的多个线程中使用相同的NSSortDescriptor实例是否安全(因为我在进入@synchronized块之前要对传入数组进行排序)。以下代码是线程安全的吗?或者这是太多的过早优化

- (void) setMyArray:(NSArray*)newMyArray
{
    static NSArray *sorter = nil;

    @synchronized(self)
    {
      if ( sorter == nil )
      {
        NSSortDescriptor *sortObj = [NSSortDescriptor sortDescriptorWithKey:@"size" ascending:YES];
        sorter = [[NSArray arrayWithObject:sortObj] retain];
      }
    }

    NSArray *sorted = [myNewArray sortedArrayUsingDescriptors:sorter];

    @synchronized(self) 
    {
       // set iVar from sorted array...
    }
}

NSSortDescriptor
没有任何可见的更改方法,也没有任何理由在内部更改其状态,因此它很可能是线程安全的(除非苹果在框架代码中对其进行了黑客攻击,我对此表示怀疑)

至于优化,如果没有实际的分析,它(几乎)总是不成熟的。在这种情况下,我将对静态var做同样的事情——主要是为了有一个明确声明/定义排序策略的地方

各州:

不可变对象通常是 线程安全;一旦你创建了它们,你就可以 可以安全地将这些对象传递到和 从线程。当然,当使用 不可变对象,您仍然需要 记住使用引用计数 正确地如果你不适当地 释放未保留的对象, 稍后可能会导致异常


正如hoha所观察到的,NSSortDescriptor是不可变的,因此它是线程安全的,除非另有特别说明(通常在类文档中)。

当没有相关文档时,盲目地假设事物是线程安全的通常是不好的。您无法知道它是在内部操纵缓存还是进行任何其他形式的修改。永远不要假设任何东西都是线程安全的。如果某个东西是线程安全的,那么它将被明确地记录下来。做出任何类似的假设都会导致崩溃(并且经常会在软件更新后导致崩溃)。@凯文·巴拉德:是的,我没有。我无法想象排序描述符中的任何可变状态,但我也无法证明它的不存在。这就是为什么我说“很可能”。顺便说一句,“线程编程指南”指出“不可变对象通常是线程安全的”,这对我来说是间接的证据。@bbum:“它将被明确地记录下来。”。这是否意味着Cocoa中只有一个线程安全类(
NSUserDefaults
)?顺便说一句,我同意该文档在这方面过于松散,并要求对其进行增强。我知道不可变对象是线程安全的,但正如您在下面的回复中所指出的,仅仅因为它看起来是不可变的,就认为它是不可变的是不好的。。。文件也没有说它是不可变的。我还将在本例中的文档上归档一个bug,以便今后更清晰。归档雷达,bug ID 9131037。