В чем разница между многопоточностью и асинхронностью?

«В чем разница между многопоточностью и асинхронностью?» — вопрос из категории Многопоточность, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Многопоточность и асинхронность — это связанные, но различные концепции параллельного программирования.

Многопоточность (Concurrency)

Это одновременное выполнение нескольких потоков исполнения. Потоки могут выполняться параллельно на разных ядрах CPU или разделять время на одном ядре.

// Создание и запуск отдельного потока (низкоуровневый подход)
import Foundation
Thread.detachNewThread {
    print("Выполняюсь в фоновом потоке: (Thread.current)")
}

// Высокоуровневая многопоточность через GCD
DispatchQueue.global(qos: .background).async {
    // Этот блок выполняется в фоновом потоке
    let result = heavyCalculation()
    DispatchQueue.main.async {
        // Возвращаем результат в главный поток
        updateUI(with: result)
    }
}

Асинхронность (Asynchrony)

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

// Асинхронность с completion handler (до Swift 5.5)
func fetchData(completion: @escaping (Result<Data, Error>) -> Void) {
    URLSession.shared.dataTask(with: url) { data, _, error in
        // Вызов completion — это асинхронный колбэк
        completion(.success(data!))
    }.resume()
    // Функция fetchData завершается немедленно, не дожидаясь ответа сети
}

// Асинхронность с async/await (Swift 5.5+)
func fetchData() async throws -> Data {
    // Код приостанавливается, но поток не блокируется
    let (data, _) = try await URLSession.shared.data(from: url)
    return data
}

Task {
    let data = try await fetchData() // Неблокирующее ожидание
    print(data)
}

Ключевые отличия

Концепция Многопоточность Асинхронность
Суть Параллельное выполнение кода Неблокирующее выполнение задач
Основная цель Использование нескольких ядер CPU Отзывчивость, отсутствие блокировок
Абстракция Потоки (Thread), очереди (DispatchQueue) async/await, completion handlers, promises
Взаимосвязь Асинхронный код часто использует многопоточность для выполнения Не все асинхронные операции требуют новых потоков

Простой аналог:

  • Многопоточность — это несколько поваров на кухне.
  • Асинхронность — это повар, который, поставив суп вариться, не стоит над кастрюлей, а режет овощи для салата.

В современном Swift (Concurrency) с async/await система сама оптимально управляет потоками, отделяя логику асинхронности от низкоуровневой работы с потоками.