Чому паралельність?
Як тільки ви додаєте важкі завдання до свого додатку, наприклад, завантаження даних, це уповільнює роботу вашого інтерфейсу або навіть заморожує його. Паралельність дозволяє виконувати 2 або більше завдань «одночасно». Недоліком цього підходу є та безпека ниток, яку не завжди так легко контролювати. Fe, коли різні завдання хочуть отримати доступ до тих самих ресурсів, як спроба змінити одну і ту ж змінну в різних потоках або доступ до ресурсів, вже заблокованих різними потоками.
Є кілька абстракцій, про які нам слід знати.
- Черги.
- Синхронне / асинхронне виконання завдань.
- Пріоритети.
- Поширені неприємності.
Черги
Має бути послідовним або одночасним . А також глобальні чи приватні одночасно.
При послідовних чергах завдання будуть виконуватися одне за одним, тоді як при одночасних чергах завдання виконуватимуться одночасно і виконуватимуться за несподіваними графіками. Ця ж група завдань займе більше часу в послідовній черзі порівняно з одночасною чергою.
Ви можете створювати власні приватні черги (як послідовні, так і одночасні ) або використовувати вже доступні глобальні (системні) черги . Основна чергу є єдиною послідовною чергою з усіх глобальних черг .
Настійно рекомендується не виконувати важкі завдання, які не посилаються на роботу інтерфейсу, в основній черзі (завантаження даних з мережі), а натомість робити їх в інших чергах, щоб інтерфейс не розморожувався та реагував на дії користувача. Якщо ми дозволимо змінювати інтерфейс в інших чергах, зміни можуть бути внесені за іншим і несподіваним графіком та швидкістю. Деякі елементи інтерфейсу можна намалювати до або після того, як вони потрібні. Це може призвести до збою інтерфейсу користувача. Також нам слід пам’ятати, що оскільки глобальні черги - це системні черги, на них система може виконувати деякі інші завдання.
Якість обслуговування / пріоритет
Черги також мають різне qos (Якість обслуговування), яке встановлює завдання, що виконує пріоритет (тут від найвищого до найнижчого):
.userInteractive - основна черга
.userInitiated - для ініційованих користувачем завдань, на які користувач чекає певної відповіді
.utility - для завдань що займає певний час і не вимагає негайної реакції, наприклад, робота з даними
.background - для завдань, які не пов’язані з візуальною частиною і які не є суворими на час завершення).
Існує також черга
.default, яка не передає інформацію qos . Якщо виявити qos qos було неможливобуде використовуватися між .userInitiated та .utility .
Завдання можуть виконуватися синхронно або асинхронно .
Синхронна функція повертає керування поточною чергою лише після завершення завдання. Він блокує чергу і чекає, поки завдання не буде закінчено.
Асинхронна функція повертає управління до поточної черги відразу після того, як завдання було надіслано для виконання в іншій черзі. Це не чекає, поки завдання буде закінчено. Це не блокує чергу.
Загальні проблеми.
Найпопулярніші помилки, які допускають програмісти при проектуванні одночасних додатків, такі:
- Умова гонки - викликається, коли робота програми залежить від порядку виконання частин коду.
- Інверсія пріоритету - коли завдання з вищим пріоритетом чекають завершення завдань з меншим пріоритетом через блокування деяких ресурсів
- Тупик - коли кілька черг нескінченно чекають джерел (змінних, даних тощо), які вже заблоковані деякими з цих черг.
НІКОЛИ не викликайте функцію синхронізації в головній черзі .
Якщо ви викличете функцію синхронізації в основній черзі, вона заблокує чергу, а також чекатиме завершення завдання, але завдання ніколи не буде завершено, оскільки воно навіть не зможе запуститись, оскільки вже заблоковано. Це називається глухим кутом .
Коли використовувати синхронізацію?
Коли нам потрібно почекати, поки завдання буде закінчено. Fe, коли ми переконуємось, що якусь функцію / метод не викликають подвійно. Якщо ми маємо синхронізацію і намагаємось не допустити її подвійного виклику, поки вона не буде повністю завершена. Ось деякий код для цього:
Як дізнатися, що спричинило звіт про помилку на пристрої IOS?
DispatchQueue.main.sync
з фонового потоку?