2012-02-10 2 views
16

Apple's multithreading docs не перечислены NSIndexPath как темы или нет! Как неизменный класс, я обычно ожидал, что он будет потокобезопасным.Является ли NSIndexPath потокобезопасным?

Раньше я был уверен, что в документации было указано, что экземпляры NSIndexPath были разделены и уникальны по всему миру. Это, кажется, исчезло сейчас, хотя, заставив меня подозревать, что дизайн был пересмотрен для iOS5/Mac OS X 10.7.

Я вижу довольно много отчетов о сбоях от клиентов на Mac OS X 10.6 (Snow Leopard), которые, кажется, сбой, пытаясь получить доступ к указательному пути. Таким образом, я задаюсь вопросом: являются ли фактические потоки потоками безопасными, но что логика вытаскивания их из общего кэша не является? Кто-нибудь знает?

Вот пример трассировки стека КСТАТИ:

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 экземпляр пытается сравнивать себя с высвобождены, например.

+1

Что вы делаете с этими указательными дорожками и где происходит сбой? Ошибки многопоточности таинственны, сбой «NSIndexPath» не обязательно означает, что проблема находится в 'NSIndexPath'. – hamstergene

+0

Выполняю запрос на выборку, а затем сортирую результаты на основе метода '-indexPath'. Внутренне каждый раз, когда он вызывается, этот метод создает путь индекса, который представляет позицию объекта в дереве. Я подозреваю, что мне передают совместно используемые 'NSIndexPath', которые затем освобождаются вскоре после этого в другом потоке. –

+0

Где находится NSIndexPath? Является ли это свойство выбранного объекта? –

ответ

4

До сих пор лучший ответ у меня есть, как я подозреваю:

На OS X 10.7 и прошивкой 5, NSIndexPath является поточно. До этого экземпляры являются потокобезопасными, потому что они неизменяемы, но совместного поиска существующих экземпляров нет.

На мой метод, который возвращает индекс пути по требованию, я сделал это:

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

    return [[result retain] autorelease]; 
} 

С момента внедрения этой последней строки кода, у нас не было больше никаких сообщений о падениях из индексных путей.

Пути по индексу создаются по -indexPathByAddingIndex: или +indexPathWithIndex:.

Результаты, которые я вижу, делают меня вполне уверенным, что (до 10.7/iOS5) эти методы возвращают существующий экземпляр NSIndexPath.Этот экземпляр не сохраняется в текущем потоке каким-либо образом, поэтому поток, который сначала создал экземпляр (основной в нашем случае), освобождает путь (вероятно, через всплытие пула авторесурсов) и оставив наш рабочий поток с обвисшим указателем, который падает при использовании, как видно в вопросе.

Это все немного страшно, потому что, если мой анализ верен, танец retain/autorelease, который я добавил, просто заменяет одно состояние гонки другим, менее вероятным.

До 10.7/iOS5 я могу думать только об одном обходном пути: Ограничить все создание указательных путей в основной поток. Это может быть довольно медленным, если такой код называется много, поэтому его можно было бы улучшить - за счет памяти - за счет использования своего кеша экземпляра для потоковых потоков. Если кеш сохраняет путь, то вы знаете, что он не будет освобожден от основного потока.

1

Apple не указывает список NSIndexPath как безопасный поток, но они говорят, что неизменяемые классы, как правило, безопасны и изменяемы, как правило, нет. Поскольку NSIndexPath неизменен, можно предположить, что он потокобезопасен.

Но «потоковый сейф» не означает, что он не может вызывать сбои, будучи выпущенным одним потоком, прежде чем использовать его на другом. Потоковый сейф обычно означает, что его методы мутаторов содержат блокировку для предотвращения сбоев из-за одновременного задания свойств двух потоков (поэтому классы без методов мутаторов, как правило, являются потокобезопасными, хотя ленивые геттеры и общие экземпляры также могут вызывать проблемы).

Похоже, что ваша ошибка, скорее всего, связана с использованием пула автозапуска или каким-либо другим механизмом, который заставляет ваш объект быть выпущенным в то время вне вашего контроля. Вероятно, вы должны убедиться, что любые объекты с одновременным доступом хранятся в свойствах долгоживущих классов, чтобы вы могли контролировать их продолжительность жизни.

Создание автореализованного объекта и доступ к нему из другого потока после того, как вы удалили все сильные ссылки на него, - это опасная гоночная игра, которая может вызвать сбои в трассировке, независимо от того, является ли рассматриваемый объект «потоком» безопасно".

+0

Да, я понимаю разнообразие опасностей в многопоточном коде. Я не создаю эти объекты в одном потоке и ожидаю, что они останутся в другом потоке. Я создаю объекты, задавая «NSIndexPath» для них в рабочем потоке. Я понимаю, что в 10.6 и более ранних версиях экземпляры NSIndexPath' находятся в глобальном масштабе. Я подозреваю, что этот глобальный кеш не является потокобезопасным, а не отдельными экземплярами. –

+1

Вы все еще можете прочитать документы iOS 4.3/OS 10.6 в Organizer в Xcode, если вы загрузите старые наборы документов и выполните поиск всех наборов doc. Я нашел строку, на которую вы ссылаетесь: «Объекты NSIndexPath уникальны и разделены. Если путь индекса, содержащий указанный индекс или индексы, уже существует, этот объект возвращается вместо нового экземпляра». И да, похоже, что они были удалены в последних документах, поэтому, возможно, вы правы в том, что NSIndexPath не является потокобезопасным в соответствии с 10.6. –

+0

Ага, я забыл, что вы можете добраться до старых документов еще! –

Смежные вопросы