Пишу простым языком об iOS разработке на Swift и мобильной разработке в целом.
Обо мне: https://t.me/hardworkerIT/3
Чат: @hardworkerChatIT
Канал про разработку и жизнь в ИТ: @itDenisov
Вакансии по мобильной разработке: @mobileDevJobs
Post #194
1.3K
🔢 Swift Concurrency: как Executors и Actors управляют потоками.
Разберем как на самом деле работают потоки в Swift Concurrency. Если вы думаете, что async/await — это просто синтаксический сахар, приготовьтесь удивляться. Под капотом скрывается мощная система управления задачами через Executors и Actors.
Из чего состоит Swift Concurrency:
🔸 Task: единица асинхронной работы (как поток для синхронных функций).
🔸 Job: часть задачи между точками await (suspension points).
🔸 Executor: планировщик, который распределяет Job по потокам.
🔸 Cooperative Thread Pool: пул потоков (число = числу ядер устройства).
Типы Executors:
🔸 Global Concurrent Executor: дефолтный, распределяет задачи по потокам из пула.
🔸 Serial Executors: для акторов, выполняет задачи последовательно.
🔸 Main Actor Executor: специальный для главного потока.
Пример кастомного Executor:
Actors: безопасность данных.
Акторы защищают от гонки данных, выполняя методы последовательно:
Как работает последовательность.
Даже при параллельных вызовах актор гарантирует порядок:
Global Actors.
Зачем это нужно, спросите вы. Чтобы разные функции и классы использовали один общий актор. Например:
🔸 Все сетевые запросы через один NetworkActor
🔸 Все операции с базой данных через DatabaseActor
🔸 Все аналитические события через AnalyticsActor
Важные особенности:
🔸 Потоки не блокируются: await освобождает поток для других задач.
🔸 Автоматическое планирование: система сама выбирает оптимальный поток.
🔸 Безопасность по умолчанию: компилятор следит за изоляцией данных.
Когда использовать:
🔹 Global Concurrent: для независимых задач.
🔹 Serial Executor: когда важен порядок выполнения.
🔹 Main Actor: для работы с UI.
🔹 Custom Executors: для специальных требований к планированию.
💡 Вывод:
Swift Concurrency это не просто async/await, а целая экосистема для безопасной многопоточности. Понимание работы Executors и Actors поможет писать более эффективный и надежный код.
➡️ Подписаться на канал
Мобильный трудоголик
Разберем как на самом деле работают потоки в Swift Concurrency. Если вы думаете, что async/await — это просто синтаксический сахар, приготовьтесь удивляться. Под капотом скрывается мощная система управления задачами через Executors и Actors.
Из чего состоит Swift Concurrency:
🔸 Task: единица асинхронной работы (как поток для синхронных функций).
🔸 Job: часть задачи между точками await (suspension points).
🔸 Executor: планировщик, который распределяет Job по потокам.
🔸 Cooperative Thread Pool: пул потоков (число = числу ядер устройства).
Типы Executors:
🔸 Global Concurrent Executor: дефолтный, распределяет задачи по потокам из пула.
🔸 Serial Executors: для акторов, выполняет задачи последовательно.
🔸 Main Actor Executor: специальный для главного потока.
Пример кастомного Executor:
// Создаем свой планировщик
final class CustomExecutor: TaskExecutor {
func enqueue(_ job: consuming ExecutorJob) {
print("Запускаем задачу на потоке: \(Thread.current)")
job.runSynchronously(on: asUnownedTaskExecutor())
}
func asUnownedTaskExecutor() -> UnownedTaskExecutor {
UnownedTaskExecutor(ordinary: self)
}
}
// Использование
Task(executorPreference: CustomExecutor()) {
print("Выполняем работу")
try await Task.sleep(for: .seconds(1))
print("Завершаем работу")
}
Actors: безопасность данных.
Акторы защищают от гонки данных, выполняя методы последовательно:
actor SafeCounter {
private var count = 0
func increment() {
count += 1
print("Текущее значение: \(count)")
}
}
// Использование
let counter = SafeCounter()
Task {
await counter.increment() // Безопасный доступ
}
Как работает последовательность.
Даже при параллельных вызовах актор гарантирует порядок:
await withTaskGroup { group in
for i in 0..<5 {
group.addTask { await counter.increment() }
}
}
// Вывод всегда будет: 1, 2, 3, 4, 5
Global Actors.
@MainActor вы уже знаете, но можно создавать и свои глобальные акторы:
@globalActor
actor NetworkActor {
static let shared = NetworkActor() // Единый экземпляр на все приложение
}
@NetworkActor
func fetchData() async -> Data {
// Все вызовы этого метода будут последовательными
// даже из разных частей приложения!
}
@NetworkActor
class ApiService {
// Все методы класса будут автоматически изолированы
func getUser() async -> User {
}
}
Зачем это нужно, спросите вы. Чтобы разные функции и классы использовали один общий актор. Например:
🔸 Все сетевые запросы через один NetworkActor
🔸 Все операции с базой данных через DatabaseActor
🔸 Все аналитические события через AnalyticsActor
Важные особенности:
🔸 Потоки не блокируются: await освобождает поток для других задач.
🔸 Автоматическое планирование: система сама выбирает оптимальный поток.
🔸 Безопасность по умолчанию: компилятор следит за изоляцией данных.
Когда использовать:
🔹 Global Concurrent: для независимых задач.
🔹 Serial Executor: когда важен порядок выполнения.
🔹 Main Actor: для работы с UI.
🔹 Custom Executors: для специальных требований к планированию.
💡 Вывод:
Swift Concurrency это не просто async/await, а целая экосистема для безопасной многопоточности. Понимание работы Executors и Actors поможет писать более эффективный и надежный код.
➡️ Подписаться на канал
Мобильный трудоголик
- 👍 24
- ❤ 6
- 🔥 4
- 🙏 3

