В чем разница между асинхронной (async) и параллельной (concurrent) очередью в GCD?

Ответ

Async и Concurrent — это разные аспекты работы с очередями в Grand Central Dispatch (GCD).

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

  • Способ отправки задачи. Задача ставится в очередь и выполняется, не блокируя текущий поток.
  • Не гарантирует параллелизм. Асинхронная задача может выполняться на серийной (serial) очереди, где задачи идут строго по одной.
  • Пример:
    // Отправка задачи асинхронно. Текущий поток продолжает работу.
    DispatchQueue.global().async {
    // Выполнение фоновой задачи
    }

Concurrent (Параллелизм)

  • Тип очереди. Очередь, которая может запускать несколько своих задач одновременно (если есть доступные потоки).
  • Всегда требует async. Задачи на параллельной очереди по умолчанию отправляются асинхронно.
  • Пример:
    // Создание параллельной очереди
    let concurrentQueue = DispatchQueue(label: "com.example.queue", attributes: .concurrent)
    // Задачи на этой очереди могут выполняться параллельно
    concurrentQueue.async { /* Задача A */ }
    concurrentQueue.async { /* Задача B */ }

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

  • async — это как отправляется задача (не дожидаясь её завершения).
  • concurrent — это свойство очереди, определяющее, могут ли её задачи выполняться параллельно.

Сочетания:

  • serialQueue.async — задачи выполняются по одной, но не блокируют вызывающий поток.
  • concurrentQueue.async — задачи могут выполняться параллельно и не блокируют вызывающий поток.

Ответ 18+ 🔞

Э, слушай, давай разберёмся с этой парой, а то народ путает, как хуй с пальцем. Async и Concurrent в GCD — это вообще про разное, как борщ и вертолёт.

Async (Асинхронность) Это, блядь, просто способ отправить задачу в очередь. Ты её кидаешь и — бац! — сразу идёшь дальше, не ждёшь, пока она там выполнится. Текущий твой поток не встаёт колом, он свободен, как ветер. Но вот парадокс, ёпта: асинхронность — это не про то, что задачи будут бежать одновременно. Нет, сука! Если очередь серийная (serial), то хоть ты шаром покатись, задачи всё равно будут выполняться строго по очереди, одна за другой. Просто ты их не ждёшь.

// Кидаем задачу асинхронно на глобальную очередь. Текущий поток не блокируется.
DispatchQueue.global().async {
    // Тут какая-нибудь тяжёлая хуйня, типа загрузки картинки
}

Concurrent (Параллелизм) А вот это уже свойство самой очереди, её внутренняя кухня. Если очередь параллельная, то она, хитрая жопа, может запускать несколько своих задач одновременно, если система даст ей свободные потоки. Но чтобы это работало, задачи на неё нужно отправлять асинхронно (async), иначе какой смысл?

// Создаём свою параллельную очередь. Атрибут .concurrent — ключевой!
let concurrentQueue = DispatchQueue(label: "com.myapp.queue", attributes: .concurrent)
// Задачи A и B могут стартануть и выполняться параллельно, если ресурсы есть.
concurrentQueue.async { /* Задача A */ }
concurrentQueue.async { /* Задача B */ }

Так в чём же разница, блядь? Да всё просто, как три копейки:

  • async — это КАК ты отправляешь задачу ("Эй, выполни это, но я тебя ждать не буду").
  • concurrent — это КАКАЯ у тебя очередь ("Я такая очередь, что мои задачи могут бежать одновременно, если смогут").

Сочетания, от которых мозг плавится:

  • serialQueue.async — Задачи встанут в строгую очередь и будут выполняться по одной, но ты их не ждёшь. Порядок гарантирован, параллелизма — ноль.
  • concurrentQueue.async — Вот тут начинается магия. Задачи могут (ключевое слово — могут!) выполняться параллельно, и ты их тоже не ждёшь. Это и есть та самая мощь GCD, ради которой всё затевалось.

Короче, async — это про твои действия, а concurrent — про настройки самой очереди. Не путай, а то получится пиздопроебибна в коде.