В чем разница между синхронными (sync) и асинхронными (async) операциями?

Ответ

Разница заключается в блокировке текущего потока выполнения.

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

Пример на Swift (Grand Central Dispatch):

let queue = DispatchQueue.global(qos: .background)

// Синхронный вызов (блокирующий)
queue.sync {
    sleep(1) // Имитация долгой задачи
    print("1. Sync task completed")
}
print("2. After sync call") // Выведется вторым

// Асинхронный вызов (неблокирующий)
queue.async {
    sleep(1)
    print("3. Async task completed")
}
print("4. After async call") // Выведется сразу, может быть третьим или четвертым

Вывод и ключевые моменты:

1. Sync task completed
2. After sync call
4. After async call
3. Async task completed
  • sync используется для синхронизации доступа к общим ресурсам (как примитив синхронизации) или когда следующий код критически зависит от результата задачи.
  • async используется для фоновых операций, чтобы не блокировать основной поток (например, для сетевых запросов или тяжелых вычислений).
  • Важно: Вызов sync на текущей очереди (особенно на главной) приводит к взаимной блокировке (deadlock).

Ответ 18+ 🔞

А, ну это ж классика, блядь! Сейчас объясню на пальцах, а то у тебя, сука, в глазах уже квадратные зрачки от этих терминов.

Разница-то, в общем, проще пареной репы, если не загоняться. Всё дело в том, блокирует ли твой код поток, или нет. Представь, что ты стоишь в очереди за пивом.

  • sync (синхронно): Ты такой: "Эй, бармен, налей пива!". И стоишь, блядь, упершись лбом в стойку, и нихуя не делаешь, пока этот оболтус не нальёт тебе пинту. Ты заблокирован, пока задача не выполнится. Только получил кружку — пошёл дальше.
  • async (асинхронно): Ты такой: "Бармен, налей пива, я пока с пацанами поболтаю". Ты сразу отваливаешь от бара и идёшь трындеть, а бармен там сам ковыряется. Задача в работе, а ты уже свободен и делаешь что хочешь.

Вот, смотри на коде, тут всё чётко:

let queue = DispatchQueue.global(qos: .background)

// Синхронный вызов (блокирующий)
queue.sync {
    sleep(1) // Прикинься, что тяжко считаешь
    print("1. Sync task completed")
}
print("2. After sync call") // Эта строка, блядь, будет ждать! Выведется ВТОРОЙ.

// Асинхронный вызов (неблокирующий)
queue.async {
    sleep(1)
    print("3. Async task completed")
}
print("4. After async call") // А эта — сразу, не дожидаясь! Выведется ТРЕТЬЕЙ.

И что в итоге вылезет на экран? Правильно, ёпта:

1. Sync task completed
2. After sync call
4. After async call
3. Async task completed

Видишь подвох? Четвёртая строка опередила третью! Потому что на async всем похуй — поставил задачу в очередь и пошёл дальше.

Где это применять, чтобы не обосраться:

  • sync — это как замок на двери от соседа-алкаша. Используешь, когда нужно синхронизировать доступ к какой-нибудь общей переменной, чтобы десять потоков в неё не писали одновременно и не получилась каша. Или когда следующий код критически зависит от результата. Типа, пока не скачался конфиг — нихуя не запускаем.
  • async — это 99% всех фоновых дел. Скачать картинку? async. Сохранить файл? async. Чтобы интерфейс не зависал, а пользователь не думал, что всё накрылось медным тазом.

И ГЛАВНОЕ ПРЕДУПРЕЖДЕНИЕ, на котором все горят, как дурачье:
Никогда, блядь, НИКОГДА не вызывай queue.sync на текущей очереди, особенно на главной (DispatchQueue.main). Это как сказать самому себе: "Я не продолжу, пока я не закончу". И всё, пиздец, взаимная блокировка (deadlock), приложение повисло, а ты чешешь репу. Запомни это, как "не срать там, где ешь".

Вот и вся магия, не так страшен чёрт, как его малюют.