Ответ 1
Почему параллелизм? Как только вы добавляете в приложение тяжелые задачи, такие как загрузка данных, это замедляет работу пользовательского интерфейса или даже останавливает его. Параллелизм позволяет выполнять 2 или более задач "одновременно". Недостаток этого подхода заключается в том, что безопасность потоков не всегда так просто контролировать. F.E. когда разные задачи хотят получить доступ к одним и тем же ресурсам, например попытаться изменить одну и ту же переменную в разных потоках или получить доступ к ресурсам, уже заблокированным разными потоками.
Есть несколько абстракций, о которых нам нужно знать.
- Очереди.
- Синхронное/Асинхронное выполнение задач.
- Приоритеты.
- Общие проблемы.
Очереди.
Должен быть последовательным или одновременным. Кроме глобального или частного одновременно.
С последовательными очередями задачи будут завершаться одна за другой, в то время как с параллельными очередями задачи будут выполняться одновременно и будут выполняться по неожиданным графикам. Та же группа задач займет намного больше времени в последовательной очереди по сравнению с параллельной очередью.
Вы можете создавать свои собственные частные очереди (как последовательные, так и одновременные) или использовать уже доступные глобальные (системные) очереди. Основная очередь является единственной последовательной очередью из всех глобальных очередей.
Настоятельно рекомендуется не выполнять сложные задачи, которые не относятся к работе пользовательского интерфейса в основной очереди (например, загружать данные из сети), а вместо этого выполнять их в других очередях, чтобы пользовательский интерфейс не был заморожен и реагировал на действия пользователя. Если мы позволим изменить пользовательский интерфейс в других очередях, изменения могут быть сделаны с другим и неожиданным графиком и скоростью. Некоторые элементы пользовательского интерфейса могут быть нарисованы до или после того, как они необходимы. Это может привести к сбою пользовательского интерфейса. Мы также должны помнить, что, поскольку глобальные очереди являются системными очередями, система может выполнять с ними некоторые другие задачи.
Качество обслуживания/приоритет.
Очереди также имеют различное qos (качество обслуживания), в котором задается задача, выполняющая приоритет (от наивысшего к низшему здесь):
.userInteractive - основная очередь
.userInitiated - для задач, инициированных пользователем, для которых пользователь ожидает ответа
.utility - для задач, которые занимают некоторое время и не требуют немедленной ответ, например, работа с данными
.background - для задач, которые не связаны с визуальной частью и не являются строгими по времени выполнения).
Существует также
.default очередь, которая не передает информацию о QOS.
Если не удалось обнаружить qos, qos будет использоваться между .userInitiated и .utility.
Задачи могут выполняться синхронно или асинхронно.
Синхронная функция возвращает управление в текущую очередь только после завершения задачи. Он блокирует очередь и ожидает завершения задачи.
Асинхронная функция возвращает управление текущей очереди сразу после того, как задача была отправлена для выполнения в другой очереди. Он не ждет, пока задача не будет завершена. Это не блокирует очередь.
Общие проблемы.
Наиболее распространенные ошибки, которые программисты допускают при проектировании параллельных приложений, следующие:
- Состояние гонки - возникает, когда работа приложения зависит от порядка выполнения частей кода.
- Инверсия приоритетов - когда задачи с более высоким приоритетом ожидают завершения задач с меньшим приоритетом из-за блокировки некоторых ресурсов
- Тупик - когда несколько очередей бесконечно ждут источников (переменных, данных и т.д.), Уже заблокированных некоторыми из этих очередей.
НИКОГДА не вызывайте функцию синхронизации в главной очереди.
Если вы вызовите функцию синхронизации в главной очереди, она заблокирует очередь, а также очередь будет ожидать завершения задачи, но задача никогда не будет завершена, поскольку она даже не сможет запуститься из-за очереди. уже заблокирован. Это называется тупик.
Когда использовать синхронизацию?
Когда нам нужно подождать, пока задача не будет завершена. F.E. когда мы проверяем, что некоторая функция/метод не вызывается дважды. F.E. у нас есть синхронизация и мы пытаемся предотвратить двойной вызов до тех пор, пока он полностью не завершится. Вот некоторый код для этой проблемы:
Какузнать, что вызвало сообщение об ошибке сбоя на устройстве IOS?