NSThread выбирает очередь и обрабатывает ее

#objective-c #multithreading #ios #thread-safety

#objective-c #многопоточность #iOS #безопасность потоков

Вопрос:

У меня есть приложение, которому необходимо отправлять собранные данные каждые X миллисекунд (и НЕ раньше!). Моей первой мыслью было собрать данные в NSMutableArray ( array1 ) на thread1 . По thread2 истечении X миллисекунд ожидания, он заменит NSMutableArray на новый ( array2 ) и затем обработает его содержимое. Однако я не хочу thread1 вносить дальнейшие изменения, array1 как только thread2 они появятся.

Вероятно, это сработает, но потокобезопасность — это не та область, где вы хотите «просто попробовать это». Каковы подводные камни этого подхода и что я должен сделать вместо этого?

(Кроме того, если thread2 на самом деле это экземпляр NSTimer, как меняется проблема / ответ? Будет ли все это происходить в одном потоке [что было бы хорошо для меня, поскольку обработка занимает крошечную долю миллисекунды]?).

Ответ №1:

Вам следует использовать либо NSOperationQueue, либо Grand Central Dispatch. По сути, вы создадите операцию, которая получает ваши данные и загружает их по истечении X миллисекунд. Каждая операция будет независимой, и вы можете настроить очередь в зависимости от того, сколько одновременных операций вы разрешаете, приоритет операций и т.д.

Документы Apple по параллелизму должны помочь:

http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html

Ответ №2:

Подводные камни этого подхода связаны с тем, что вы «заменяете» NSArray на новую. Представьте, что thread1 получает ссылку на массив, и в то же время thread2 меняет местами массивы и завершает обработку. Thread1 теперь выполняет запись в мертвый массив (тот, который больше не будет обрабатываться), даже если это всего на несколько миллисекунд. Способ предотвратить это, конечно, заключается в использовании синхронизированных блоков кода (т. Е. сделать ваш код «потокобезопасным») в критических разделах, но довольно сложно не превысить отметку и синхронизировать слишком большую часть вашего кода (жертвуя производительностью).

Таким образом, риски заключаются в том, что вы будете:

  • Создайте код, который не является потокобезопасным
  • Создайте код, который злоупотребляет синхронизацией и работает медленно (а потоки уже имеют издержки производительности)
  • Создайте какую-нибудь комбинацию из этих двух: медленный, небезопасный код.

Идея состоит в том, чтобы «перейти от потоков», о чем и эта ссылка.