多线程 – NSIndexPath线程安全吗?

Apple’s multithreading docs不列出NSIndexPath作为线程安全吗?作为一个不可改变的课程,我通常会期望它是线程安全的。

以前,我确定用于说明NSIndexPath实例是共享的和全局唯一的文档。现在似乎已经消失了,导致我怀疑iOS5 / Mac OS X 10.7的设计被修改了。

我在Mac OS X 10.6(Snow Leopard)上看到很多客户的崩溃报告似乎正在崩溃,试图访问索引路径。所以我想知道:实际的线程是否安全,但是把它们从共享缓存中拉出来的逻辑不是吗?有人有任何见解吗?

这是一个示例堆栈跟踪BTW:

Dispatch queue: com.apple.root.default-priority
0 libobjc.A.dylib 0x96513f29 _cache_getImp + 9
1 libobjc.A.dylib 0x965158f0 class_respondsToSelector + 59
2 com.apple.CoreFoundation 0x948bcb49 ___forwarding___ + 761
3 com.apple.CoreFoundation 0x948bc7d2 _CF_forwarding_prep_0 + 50
4 com.apple.Foundation 0x994b10c5 -[NSIndexPath compare:] + 93
5 com.apple.Foundation 0x99415686 _NSCompareObject + 76
6 com.apple.CoreFoundation 0x948af61c __CFSimpleMergeSort + 236
7 com.apple.CoreFoundation 0x948af576 __CFSimpleMergeSort + 70
8 com.apple.CoreFoundation 0x948af38c CFSortIndexes + 252
9 com.apple.CoreFoundation 0x948fe80d CFMergeSortArray + 125
10 com.apple.Foundation 0x994153d3 _sortedObjectsUsingDescriptors + 639
11 com.apple.Foundation 0x994150d8 -[NSArray(NSKeyValueSorting) sortedArrayUsingDescriptors:] + 566

对我来说,这是一个NSIndexPath实例,试图将其与释放的实例进行比较。

最佳答案
到目前为止,我所怀疑的最好的答案是:

从OS X 10.7和iOS 5起,NSIndexPath是线程安全的。在此之前,实例是线程安全的,因为它们是不可变的,但是对现有实例的共享检索不是。

对于按需返回索引路径的方法,我做到了这一点:

- (NSIndexPath *)indexPath;
{
    NSIndexPath *result = … // create the path as appropriate

    return [[result retain] autorelease];
}

自从执行最后一行代码之后,我们就没有更多的索引路径的崩溃报告。

索引路径由-indexPathByAddingIndex:或indexPathWithIndex:创建。

我看到的结果使我相当确定(10.7 / iOS5之前)这些方法返回一个现有的NSIndexPath实例。该实例不以任何方式保留当前线程,所以首先创建实例的线程(在我们的例子中是主要的)是释放路径(可能通过弹出自动释放池),并使工作线程留下悬挂指针,在使用时崩溃,如问题所示。

这是一个可怕的,因为如果我的分析是正确的,我添加的保留/自动释放舞只是替换一个竞争条件与另一个,较不可能的一个。

在10.7 / iOS5之前,我只能想到一个真正的解决方法:将所有创建索引路径限制到主线程。如果这样的代码被称为很多,那么这可能是相当慢的,所以可以通过维护一些你自己的实例缓存来改善后台线程的使用。如果缓存保留一个路径,那么你知道它不会被主线程释放。

转载注明原文:多线程 – NSIndexPath线程安全吗? - 代码日志