Ответ
Работа с несколькими потоками сопряжена с рядом классических проблем:
| Проблема | Описание | Пример риска в Swift/iOS |
|---|---|---|
| Состояние гонки (Race Condition) | Неопределённый результат из-за неконтролируемого порядка доступа потоков к общим данным. | Неатомарное изменение общего счётчика из нескольких потоков приводит к потере обновлений. |
| Взаимная блокировка (Deadlock) | Два или более потока бесконечно ожидают освобождения ресурсов, заблокированных друг другом. | Синхронный вызов (sync) на текущей serial очереди или циклическая блокировка мьютексов. |
| Инверсия приоритетов (Priority Inversion) | Низкоприоритетный поток удерживает ресурс (например, блокировку), нужный высокоприоритетному, блокируя его выполнение. | Может происходить при использовании общих DispatchQueue или NSLock с разными QoS. |
| Голодание (Starvation) | Поток не может получить доступ к необходимым ресурсам и не прогрессирует. | Долгие задачи на serial очереди или неправильная настройка приоритетов в OperationQueue. |
| Проблемы с памятью | Утечки, висячие указатели из-за неправильного управления жизненным циклом объектов между потоками. | Сильные ссылки в захватах замыканий, удерживающие объекты в фоновых потоках. |
Конкретные примеры и решения:
- Гонка данных:
var unsafeCounter = 0 DispatchQueue.concurrentPerform(iterations: 1000) { _ in unsafeCounter += 1 // НЕБЕЗОПАСНО! Итоговое значение будет меньше 1000. } // Решение: Использовать изолированный актор или очередь с барьером. - Обновление UI не из главного потока:
DispatchQueue.global().async { self.label.text = "New Text" // КРАШ или неопределённое поведение. } // Решение: Всегда обновлять UI через `DispatchQueue.main` или `MainActor`.
Основные инструменты предотвращения: Акторы (actor), семафоры (DispatchSemaphore), очереди с барьерами (DispatchQueue.barrier), атомарные операции, а также архитектурные паттерны, минимизирующие общее состояние.