О потоковом программировании

Много лет максимальная производительность компьютера была ограничена в основном скоростью единственного микропроцессора в основе компьютера. Поскольку скорость отдельных процессоров начала достигать их практических пределов, однако, производители микросхем, переключенные на многожильные проекты, дав компьютеру возможность выполнить многократные задачи одновременно. И несмотря на то, что OS X использует в своих интересах эти ядра каждый раз, когда он может для выполнения связанных с системой задач, собственные приложения могут также использовать в своих интересах их через потоки.

Что такое потоки?

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

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

В непараллельном приложении существует только один поток выполнения. Тот поток запускается и заканчивается Вашим приложением main подпрограмма и ответвления один за другим к различным методам или функциям для реализации полного поведения приложения. В отличие от этого, приложение, поддерживающее параллелизм, запускается с одного потока и добавляет более по мере необходимости для создания дополнительных путей выполнения. Каждый новый путь имеет свою собственную подпрограмму запуска, работающую независимо от кода в приложении main подпрограмма. Наличие многократных потоков в приложении обеспечивает два очень важных потенциальных преимущества:

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

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

Конечно, потоки не являются панацеей для решения проблем производительности приложения. Вместе с преимуществами, предлагаемыми потоками, прибывает потенциальные проблемы. Наличие разнообразных путей выполнения в приложении может добавить значительную сумму сложности к Вашему коду. Каждый поток должен скоординировать свои действия с другими потоками, чтобы препятствовать тому, чтобы он повредил информацию приложения состояния. Поскольку потоки в единственном приложении совместно используют то же пространство памяти, у них есть доступ ко всем тем же структурам данных. Если два потока пытаются управлять той же структурой данных одновременно, один поток мог бы перезаписать чьи-либо изменения в пути, повреждающем получающуюся структуру данных. Даже с надлежащими мерами защиты на месте, все еще необходимо не упустить оптимизацию компилятора, представляющую тонкий (и не настолько тонкая) ошибки в код.

Поточная обработка терминологии

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

Если Вы знакомы с системами UNIX, можно найти, что термин «задача» используется по-другому этим документом. В системах UNIX термин «задача» используется время от времени для обращения к рабочему процессу.

Этот документ принимает следующую терминологию:

Альтернативы потокам

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

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

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

Табличные 1-1  технологии Альтернативы к потокам

Технология

Описание

Объекты операции

Представленный в OS X v10.5, объект операции является оберткой для задачи, которая обычно выполнялась бы на вторичном потоке. Эта обертка скрывает аспекты управления потоком выполнения задачи, оставлять Вас освобождает для фокусирований на самой задаче. Вы обычно используете эти объекты в сочетании с объектом очереди работы, фактически управляющим выполнением объектов операции на одном или более потоках.

Для получения дополнительной информации о том, как использовать объекты операции, см. Руководство по программированию Параллелизма.

Grand Central Dispatch (GCD)

Представленный в Mac OS X v10.6, Центральная Отгрузка является другой альтернативой потокам, позволяющей Вам фокусироваться на задачах, которые необходимо выполнить, а не на управлении потоком. С GCD Вы определяете задачу, Вы хотите выполнить и добавить его к рабочему списку, обрабатывающему планирование Вашей задачи на надлежащем потоке. Рабочие списки принимают во внимание число доступных ядер и текущей загрузки для выполнения задач более эффективно, чем Вы могли сделать себя с помощью потоков.

Для получения информации о том, как использовать GCD и рабочие списки, см. Руководство по программированию Параллелизма

Уведомления времени простоя

Для задач, которые являются относительно коротким и очень низким приоритетом, уведомления времени простоя позволяют Вам выполнить задачу в то время, когда Ваше приложение не так занято. Какао предоставляет поддержку для уведомлений времени простоя с помощью NSNotificationQueue объект. Для запроса уведомления времени простоя отправьте уведомление значению по умолчанию NSNotificationQueue объект с помощью NSPostWhenIdle опция. Очередь задерживает поставку Вашего объекта уведомления, пока цикл выполнения не становится неактивным. Для получения дополнительной информации см., что Уведомление Программирует Темы.

Асинхронные функции

Системные интерфейсы включают много асинхронных функций, предоставляющих автоматический параллелизм Вам. Этот APIs может использовать системных демонов и процессы или создать пользовательские потоки, чтобы выполнить их задачу и возвратить результаты Вам. (Фактическая реализация не важна, потому что она разделяется от Вашего кода.), Поскольку Вы разрабатываете свое приложение, ищите функции, предлагающие асинхронное поведение и рассматривающие использование их вместо того, чтобы использовать эквивалентную синхронную функцию на пользовательском потоке.

Таймеры

Можно использовать таймеры на основном потоке приложения для выполнения периодических задач, которые слишком тривиальны для требования потока, но все еще требующих обслуживания равномерно. Для получения информации о таймерах посмотрите Источники Таймера.

Отдельные процессы

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

Поточная обработка поддержки

Если у Вас есть существующий код, использующий потоки, OS X и iOS обеспечивают несколько технологий для создания потоков в Ваших приложениях. Кроме того, обе системы также предоставляют поддержку для управления и синхронизации работы, которая должна быть выполнена на тех потоках. Следующие разделы описывают некоторые ключевые технологии, о которых необходимо знать при работе с потоками в OS X и iOS.

Поточная обработка пакетов

Несмотря на то, что механизм конкретной реализации для потоков является потоками Маха, Вы редко (если когда-нибудь) работаете с потоками на уровне Маха. Вместо этого Вы обычно используете более удобный POSIX API или один из его деривативов. Реализация Маха действительно обеспечивает основные характеристики всех потоков, однако, включая приоритетную модель выполнения и возможность запланировать потоки, таким образом, они независимы друг от друга.

Перечисление 2-2 перечисляет технологии поточной обработки, которые можно использовать в приложениях.

Табличные 1-2  технологии Потока

Технология

Описание

Потоки какао

Какао реализует потоки с помощью NSThread класс. Какао также обеспечивает методы на NSObject для порождения новых потоков и выполнения кода уже рабочих потоков. Для получения дополнительной информации посмотрите Используя NSThread и Используя NSObject для Порождения Потока.

Потоки POSIX

Потоки POSIX обеспечивают интерфейс на базе С для создания потоков. Если Вы не пишете приложение Какао, это - лучший выбор для создания потоков. Интерфейс POSIX относительно прост использовать и предлагает вполне достаточную гибкость для конфигурирования Ваших потоков. Для получения дополнительной информации посмотрите Используя Потоки POSIX

Multiprocessing Services

Multiprocessing Services является устаревшим интерфейсом на базе С, используемым приложениями, переходящими от более старых версий Mac OS. Эта технология доступна в OS X только и должна избежаться для любой новой разработки. Вместо этого необходимо использовать NSThread класс или потоки POSIX. При необходимости в большей информации об этой технологии см. Руководство по программированию Multiprocessing Services.

На прикладном уровне все потоки ведут себя по существу тем же способом как на других платформах. После запуска потока поток работает в одном из трех основных состояний: выполнение, готовое, или блокированное. Если поток в настоящее время не работает, он или блокируется и ожидающий ввода, или это готово работать, но не запланировало делать так все же. Поток продолжает двигаться вперед-назад среди этих состояний, пока он наконец не выходит и перемещается в завершенное состояние.

При создании нового потока необходимо указать функцию точки входа (или метод точки входа в случае потоков Какао) для того потока. Эта функция точки входа составляет код, Вы хотите работать на потоке. Когда функция возвращается, или когда Вы завершаете поток явно, остановки потока постоянно, и предъявлен претензии системой. Поскольку потоки являются относительно дорогими для создания с точки зрения памяти и время, поэтому рекомендуется, чтобы функция точки входа сделала существенное количество работы или установила цикл выполнения для обеспечения повторяющейся работы, которая будет выполняться.

Для получения дополнительной информации о доступных технологиях поточной обработки и как использовать их, посмотрите управление потоком.

Выполненные циклы

Цикл выполнения является частью инфраструктуры, используемой для управления событиями, поступающими асинхронно в поток. Цикл выполнения работает путем контроля одного или более источников событий для потока. Когда события поступают, система будит поток и диспетчеризирует события циклу выполнения, тогда диспетчеризирующему их обработчикам, которые Вы указываете. Если никакие события не присутствуют и готовы быть обработанными, цикл выполнения помещает поток для сна.

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

Для конфигурирования цикла выполнения все, что необходимо сделать, запустить поток, получить ссылку на объект цикла выполнения, установить обработчики событий и сказать циклу выполнения работать. Инфраструктура, предоставленная OS X, обрабатывает конфигурацию цикла выполнения основного потока для Вас автоматически. Если Вы планируете создать долгосрочные вторичные потоки, однако, необходимо сконфигурировать цикл выполнения для тех потоков сами.

Подробная информация о выполненных циклах и примерах того, как использовать их, предоставлена в Выполненных Циклах.

Инструменты синхронизации

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

Блокировки обеспечивают форму защиты грубой силы для кода, который может быть выполнен только одним потоком за один раз. Наиболее распространенный тип блокировки является блокировкой взаимного исключения, также известной как взаимное исключение. Когда поток пытается получить взаимное исключение, в настоящее время сохраненное другим потоком, он блокирует, пока блокировка не выпущена другим потоком. Несколько системных платформ предоставляют поддержку для взаимоисключающих блокировок, несмотря на то, что они все на основе той же базовой технологии. Кроме того, Какао обеспечивает несколько вариантов взаимоисключающей блокировки для поддержки различных типов поведения, таких как рекурсия. Для получения дополнительной информации о доступных типах блокировок, посмотрите Блокировки.

В дополнение к блокировкам система предоставляет поддержку для условий, гарантирующих надлежащее упорядочивание задач в Вашем приложении. Условие действует как привратник, блокируя данный поток, пока условие, которое оно представляет, не становится истиной. Когда это происходит, условие выпускает поток и позволяет ему продолжаться. Уровень POSIX и платформа Основы оба предоставляют прямую поддержку для условий. (При использовании объектов операции можно сконфигурировать зависимости среди объектов операции для упорядочивания выполнения задач, которое очень подобно поведению, предлагаемому условиями.)

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

Для получения дополнительной информации о доступных инструментах синхронизации, посмотрите Инструменты Синхронизации.

Коммуникация межпотока

Несмотря на то, что хороший проект минимизирует сумму требуемой коммуникации, в некоторый момент, коммуникация между потоками становится необходимой. (Задание потока должно выполнить работу для Вашего приложения, но если результаты того задания никогда не используются, что хороший это?) Потоки, возможно, должны обработать новые запросы задания или сообщить об их прогрессе основному потоку Вашего приложения. В этих ситуациях Вам нужен способ получить информацию от одного потока до другого. К счастью, факт, что потоки совместно используют то же пространство процесса, означает, что у Вас есть много опций для коммуникации.

Существует много способов связаться между потоками, каждым с его собственными преимуществами и недостатками. Конфигурирование Локальной памяти потока перечисляет наиболее распространенные механизмы связи, которые можно использовать в OS X. (За исключением очередей сообщений и распределенных объектов Какао, эти технологии также доступны в iOS.) Методы в этой таблице перечислены в порядке увеличивающейся сложности.

Табличные 1-3  Механизмы связи

Механизм

Описание

Прямой обмен сообщениями

Поддержка приложений какао возможность выполнить селекторы непосредственно на других потоках. Эта возможность означает, что один поток может по существу выполнить метод на любом другом потоке. Поскольку они выполняются в контексте целевого потока, сообщения отправили, этот путь автоматически сериализируются на том потоке. Для получения информации о входных источниках посмотрите, что Какао Выполняет Селекторные Источники.

Глобальные переменные, общая память и объекты

Другой простой способ передать информацию между двумя потоками состоит в том, чтобы использовать глобальную переменную, общий объект или совместно использованный блок памяти. Несмотря на то, что совместно используемые переменные быстры и просты, они также более хрупки, чем прямой обмен сообщениями. Совместно используемые переменные должны быть тщательно защищены с блокировками или другими механизмами синхронизации для обеспечения правильности кода. Отказ сделать так мог привести к условиям состязания, поврежденным данным или катастрофическим отказам.

Условия

Условия являются инструментом синхронизации, который можно использовать для управления, когда поток выполняет определенную часть кода. Можно думать об условиях как контролеры, позволяя потоку работать только, когда удовлетворяют установленному условию. Для получения информации о том, как использовать условия, посмотрите Используя Условия.

Выполненные источники цикла

Пользовательский источник цикла выполнения является тем, который Вы устанавливаете для получения специализированных сообщений на потоке. Поскольку они управляемы событиями, выполненные источники цикла помещают Ваш поток для сна автоматически, когда там не имеет отношения, который повышает эффективность потока. Для получения информации о выполненных циклах и выполненных источниках цикла, посмотрите Циклы Выполнения.

Порты и сокеты

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

Очереди сообщений

Устаревшая Multiprocessing Services определяет метод «первым пришел - первым вышел» (FIFO) абстракция очереди для управления входящими и исходящими данными. Несмотря на то, что очереди сообщений просты и удобны, они не так эффективны как некоторые другие коммуникационные методы. Для получения дополнительной информации о том, как использовать очереди сообщений, см. Руководство по программированию Multiprocessing Services.

Какао распределило объекты

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

Подсказки по проекту

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

Избегите создавать потоки явно

Запись кода создания потока вручную утомительна и потенциально подвержена ошибкам, и необходимо избежать его, когда это возможно. OS X и iOS предоставляют неявную поддержку для параллелизма через другой APIs. Вместо того, чтобы создавать поток самостоятельно, рассмотрите использование асинхронного APIs, GCD или объектов операции для выполнения работы. Эти технологии выполняют связанную с потоком работу негласно для Вас и, как гарантируют, сделают это правильно. Кроме того, технологии, такие как GCD и объекты операции разработаны для управления потоками намного более эффективно, чем собственный код когда-нибудь мог путем корректировки числа активных потоков на основе загрузки существующей системы. Для получения дополнительной информации о GCD и объектах операции, см. Руководство по программированию Параллелизма.

Сохраните свои потоки довольно Занятыми

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

Избегите совместно используемых структур данных

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

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

Потоки и Ваш пользовательский интерфейс

Если Ваше приложение имеет графический интерфейс пользователя, рекомендуется, чтобы Вы получили связанные с пользователем события и инициировали интерфейсные обновления от основного потока Вашего приложения. Этот подход помогает избежать проблем синхронизации, связанных с обработкой содержание окна рисунка и пользовательские события. Некоторые платформы, такие как Какао, обычно требуют этого поведения, но даже для тех, которые не делают, сохранение этого поведения на основном потоке имеет преимущество упрощения логики для управления Вашим пользовательским интерфейсом.

Существует несколько существенных исключений, где выгодно выполнить графические операции от других потоков. Например, можно использовать вторичные потоки, чтобы создать и обработать изображения и выполнить другие связанные с изображением вычисления. Используя вторичные потоки для этих операций может значительно увеличить производительность. Если Вы не уверены в определенной графической работе, хотя, запланируйте выполнение ее от Вашего основного потока.

Для получения дополнительной информации о потокобезопасности Какао, см. Сводку Потокобезопасности. Для получения дополнительной информации о рисовании в Какао, посмотрите, что Какао Рисует Руководство.

Знайте о способах поведения потока во время выхода

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

Создание потоков, столь же неотдельных (также известный как joinable), требует дополнительной работы с Вашей стороны. Поскольку большинство высокоуровневых технологий потока не создает joinable потоки по умолчанию, Вам, вероятно, придется использовать POSIX API для создания потока. Кроме того, необходимо добавить код к основному потоку приложения для присоединения к неотдельным потокам, когда они действительно наконец выходят. Для получения информации о создании joinable потоков посмотрите Установку Отдельного состояния Потока.

Если Вы пишете приложение Какао, можно также использовать applicationShouldTerminate: метод делегата задержать завершение приложения до более позднего времени или отменить его в целом. При задержке завершения должно было бы ожидать приложение, пока любые критические потоки не закончили свои задачи и затем вызывают replyToApplicationShouldTerminate: метод. Для получения дополнительной информации об этих методах см. Ссылку класса NSApplication.

Исключения дескриптора

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

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

В некоторых случаях обработчик исключений может быть создан для Вас автоматически. Например, @synchronized директива в Objective C содержит неявный обработчик исключений.

Завершите свои потоки чисто

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

Для получения дополнительной информации о надлежащем способе выйти из потока, посмотрите Завершение Потока.

Потокобезопасность в библиотеках

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

Для разработчиков библиотеки неблагоразумно создать блокировки только, когда приложение становится многопоточным. Если необходимо заблокировать код в некоторый момент, создайте объект блокирования рано в использовании библиотеки, предпочтительно в своего рода явном вызове для инициализации библиотеки. Несмотря на то, что Вы могли также использовать статическую функцию инициализации библиотеки для создания таких блокировок, попытайтесь сделать так только, когда нет никакого другого пути. Выполнение функции инициализации добавляет ко времени, требуемому загрузить Вашу библиотеку, и могло оказать негативное влияние на производительность.

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