Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading nsindepath线程安全吗?_Multithreading_Cocoa_Core Data_Foundation_Nsindexpath - Fatal编程技术网

Multithreading nsindepath线程安全吗?

Multithreading nsindepath线程安全吗?,multithreading,cocoa,core-data,foundation,nsindexpath,Multithreading,Cocoa,Core Data,Foundation,Nsindexpath,不要将nsindepath列为线程安全与否!作为一个不可变类,我通常希望它是线程安全的 在此之前,我确信用于声明nsindepath实例是共享的且全局唯一的文档。但现在这似乎已经消失了,这让我怀疑设计是为iOS5/MacOSX10.7修改的 我在MacOSX10.6(SnowLeopard)上看到很多客户的崩溃报告,这些报告似乎在试图访问索引路径时崩溃了。因此我想知道:实际的实例是线程安全的,但将它们从共享缓存中拉出的逻辑不是吗?有人有什么见解吗 下面是一个堆栈跟踪示例: Dispatch qu

不要将
nsindepath
列为线程安全与否!作为一个不可变类,我通常希望它是线程安全的

在此之前,我确信用于声明
nsindepath
实例是共享的且全局唯一的文档。但现在这似乎已经消失了,这让我怀疑设计是为iOS5/MacOSX10.7修改的

我在MacOSX10.6(SnowLeopard)上看到很多客户的崩溃报告,这些报告似乎在试图访问索引路径时崩溃了。因此我想知道:实际的实例是线程安全的,但将它们从共享缓存中拉出的逻辑不是吗?有人有什么见解吗

下面是一个堆栈跟踪示例:

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

对我来说,这是一个试图将自身与释放实例进行比较的
nsindepath
实例

Apple并没有特别将nsindepath列为线程安全类,但他们确实说不可变类通常是安全的,可变类通常不是。由于nsindepath是不可变的,因此可以安全地假设它是线程安全的

但是“线程安全”并不意味着它不会因为在另一个线程上使用之前被一个线程释放而导致崩溃。线程安全通常只是意味着它的mutator方法包含锁定,以防止由于两个线程同时设置属性而导致的故障(这就是为什么没有mutator方法的类通常是线程安全的,尽管惰性getter和共享实例也会导致问题)

听起来您的bug更可能是由于使用了自动释放池或其他机制,导致对象在您无法控制的时间被释放。您可能应该确保任何并发访问的对象都存储在长寿命类的属性中,以便可以控制它们的寿命


创建一个自动释放的对象并在删除所有对它的强引用后从另一个线程访问它是一个危险的赛车游戏,无论该对象是否是“线程安全”的,都可能导致难以追踪的崩溃。

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

从OSX10.7和IOS5开始,
nsindepath
是线程安全的。在此之前,实例是线程安全的,因为它们是不可变的,但现有实例的共享检索不是

对于按需返回索引路径的方法,我执行了以下操作:

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

    return [[result retain] autorelease];
}
自从实现了最后一行代码之后,我们就再也没有来自索引路径的崩溃报告了

索引路径由
-indexPathByAddingIndex:
+indexPathWithIndex:
创建

我看到的结果让我非常确定(在10.7/iOS5之前)这些方法正在返回一个现有的
nsindepath
实例。但是,当前线程不会以任何方式保留该实例,因此第一个创建该实例的线程(在本例中为main)正在释放路径(可能是通过弹出自动释放池),并给工作线程留下一个悬空指针,该指针在使用时会崩溃,如问题所示

这一切都有点可怕,因为如果我的分析是正确的,我添加的
retain
/
autorelease
舞蹈只是将一个比赛条件替换为另一个不太可能的比赛条件


在10.7/iOS5之前,我只能想到一个真正的解决方法:限制所有到主线程的索引路径的创建。如果这样的代码被大量调用,那么速度可能会相当慢,因此可以通过维护自己的实例缓存以供后台线程使用来改进(以内存为代价)。如果缓存保留了一个路径,那么您就知道它不会被主线程释放。

如何处理这些索引路径,以及在哪里发生崩溃?多线程错误是神秘的,使用
nsindepath
的崩溃并不一定意味着问题出在
nsindepath
中。我执行一个获取请求,然后根据它们的
-indepath
方法对结果进行排序。在内部,每次调用它时,该方法都会创建一个表示对象在树中位置的索引路径。我怀疑我被交给了共享的
nsindepath
s,然后不久又在另一个线程上被释放。nsindepath的起源在哪里?它是获取对象的属性吗?我在托管对象上有一个
-indepath
方法。该方法按需计算路径,通过组合使用
+indexPathWithIndex:
-indexPathByAddingIndex:
创建路径,这让我们知道,至少在单线程项目上使用nsindepath应该是安全的。因为我正在考虑自己使用它。否则,一个普通的C整数数组可能会取代它(NSIndexPath)的位置。我并不是在一个线程上创建这些对象,而是希望它们继续存在于另一个线程上。我通过在工作线程上为对象询问
nsindepath
来创建这些对象。我的理解是,在10.6及更早版本中,
nsindepath
实例是全局共享的。我怀疑此全局缓存不是线程安全的,而不是单个实例。如果下载旧的文档集并搜索所有文档集,您仍然可以在Xcode中的Organizer中读取iOS 4.3/OS 10.6文档。我找到了您所指的行:“NSIndexPath对象是唯一和共享的。如果包含指定索引的索引路径已经存在,则返回该对象而不是新实例。”是的,它似乎已在最新文档中删除,因此,在10.6下,NSIndexPath不是线程安全的,这也许是对的。