Что произойдет, если NSMutableArray будет изменен несколькими потоками одновременно?(если содержащиеся в нем объекты сохраняются в другом месте) - PullRequest
6 голосов
/ 06 сентября 2011

У меня есть NSMutableArray, содержащий много объектов.

Что произойдет, если в массив будет внесено изменение, а я создаю копию массива с помощью [NSMutableArray arrayWithArray: someArray];

Например: если объект объект удаляется из массива во время копирования?

Я не уверен, как проверить этот сценарий.

РЕДАКТИРОВАТЬ: объекты не освобождаются (так как они сохраняются в другом месте). Я просто использую этот массив в качестве справочной таблицы.

Ответы [ 3 ]

11 голосов
/ 06 сентября 2011

как вы знаете, контейнер / сборник не гарантированно безопасен для потоков. Что может произойти, если вы измените массив во время копирования или чтения? много вещей. очевидные случаи состоят в том, что он может быть перераспределен в то время, он может передать или вернуть вам недопустимую ссылку (например, самую последнюю удаленную), или он может получить доступ к объектам, которые были освобождены (из другого потока). в дополнение к вещам, которые могут привести к сбою приложения или к другим UB, оно может не возвращать правильные или согласованные значения. это неверное толкование данных. ни те, ни другие хороши.

вы не тестируете сценарий - проблемы с потоками трудно воспроизвести, и вы действительно никогда не сможете охватить все случаи. поскольку сам объект не гарантирует безопасность потоков, ваша реализация должна ограничивать доступы / мутации / взаимодействия одним потоком за раз. при работе с объектом, который используется в многопоточном контексте: каждый раз, когда вы обращаетесь или запрашиваете информацию из изменяемого состояния объекта, вы должны защищать объект (например, с помощью блокировки). следовательно, вы просто блокируете его во время использования. блокировка / копирование / разблокировка / использование копии также распространено. для NSMutableArray примерами изменяемого состояния были бы все его объекты и его количество. его операции и мутации также используют изменяемое состояние объекта, поэтому они ограничены.

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

Обновление

... Что происходит? Содержит ли копия все 5 объектов (поскольку они все равно хранятся в другом месте? Содержат ли они 4? (Даже для меня достаточно 4) Выдается ли исключение?

Если вы не защитили коллекцию должным образом, это так же хорошо, как неопределенное поведение, и вам повезло, если она вылетает.

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

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

Я призываю вас охранять должным образом или использовать другой подход. UB ЗЛО:)

5 голосов
/ 06 сентября 2011

Из документов Apple :

Изменяемые объекты, как правило, не являются поточно-ориентированными.Чтобы использовать изменяемые объекты в многопоточном приложении, приложение должно синхронизировать доступ к ним с помощью блокировок.(Для получения дополнительной информации см. «Атомные операции»).В целом, классы коллекции (например, NSMutableArray, NSMutableDictionary) не являются поточно-ориентированными, когда речь идет о мутациях.То есть, если один или несколько потоков изменяют один и тот же массив, могут возникнуть проблемы.Вы должны заблокировать места, где происходит чтение и запись, чтобы обеспечить безопасность потока.

Также из Документов Apple :

Хотя «атомарный» означает, чтодоступ к свойству является поточно-ориентированным, просто сделав все свойства в вашем классе атомарными, это не означает, что ваш класс или, в более общем смысле, ваш граф объектов является «поточно-ориентированным» - безопасность потоков не может быть выражена на уровне отдельных методов доступа.Для получения дополнительной информации о многопоточности см. Руководство по программированию потоков.

0 голосов
/ 19 февраля 2014

Если removeObject вызывается одновременно с arrayWithArray, ваша программа завершится сбоем.Если вы используете синхронизацию, заставляя выполнять removeObject либо непосредственно перед, либо сразу после arrayWithArray, вы не можете знать, сколько объектов будет иметь новый массив.Это не даст сбой сразу, но что будет делать ваш код?Вы должны четко понимать, что результатом [NSArray arrayWithArray: someArray] является массив, который не содержит содержимого someArray прямо сейчас, но содержимое someArray в какой-то момент в прошлом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...