Что произойдет, если вызвать sync на главной очереди (DispatchQueue.main)?

Ответ

Вызов DispatchQueue.main.sync из главного потока приведет к неизбежному deadlock.

Причина: Главная очередь (main) — это serial очередь. Правило то же, что и для любой serial очереди: вызов sync из той же очереди вызывает взаимную блокировку.

  • sync блокирует текущий поток (главный) и ждет, пока блок кода выполнится на целевой очереди (main).
  • Но очередь main уже занята — она выполняет тот самый метод, из которого был вызван sync, и не может приступить к новому блоку.
  • Возникает тупик: внешний код ждет sync, а sync ждет, когда очередь освободится.

Классический пример deadlock:

// Вызов из главного потока
DispatchQueue.main.sync {
    print("Этот код никогда не выполнится")
}

Решение и best practice:

  • Всегда используйте DispatchQueue.main.async для обновления UI из фоновых потоков.
  • Никогда не используйте DispatchQueue.main.sync, если есть хотя бы малейшая вероятность, что вызов происходит из главного потока. Проверить это можно с помощью Thread.isMainThread.
  • Если необходимо выполнить код синхронно и вы не уверены в текущем потоке, безопаснее использовать async.

Ответ 18+ 🔞

А, слушай, вот эта штука — классика жанра, просто пиздец! Ты представь: главная очередь, она же main, это как одна узкая тропинка в огород. Serial, блядь, очередь. Один за другим, строго по очереди.

И вот ты, такой умный, из этой самой тропинки (main) вызываешь DispatchQueue.main.sync. Ты как бы кричишь: "Эй, тропинка! Стой нахуй! Сначала выполни вот этот блок, а потом уже иди дальше!"

А тропинка-то в этот момент уже занята тобой самим, сука! Она тебя несёт, ты же из неё и зовёшь. Она не может остановиться и выполнить новый блок, потому что она ещё не закончила нести тебя до конца. А ты не можешь пойти дальше, пока блок не выполнится.

Вот и получается ебаный тупик, deadlock, блядь! Взаимная блокировка, ёпта. Ты ждёшь её, она ждёт тебя. И так до скончания времён, пока система не плюнет и не убьёт твое приложение.

Вот, смотри, самый идиотский пример, который все пишут, а потом охуевают:

// Вызов из главного потока
DispatchQueue.main.sync {
    print("Этот код никогда не выполнится")
}

"Никогда не выполнится" — это не фигура речи, это диагноз, блядь. Программа просто повиснет на этой строчке, как будто в рот ей чих-пых.

Так что же делать, мудя?

Правило простое, как хуй с горы:

  1. ВСЕГДА, блядь, ВСЕГДА используй DispatchQueue.main.async для обновления UI из фоновых потоков. Кинул задачу в очередь и пошёл дальше, не ждёшь. UI обновится, когда главная очередь до неё доберётся.
  2. НИКОГДА, нахуй, НИКОГДА не лезь с DispatchQueue.main.sync, если есть хотя бы тень сомнения, что ты уже на главном потоке. Волнение ебать, а терпения у системы — ноль.
  3. Хочешь проверить? Пожалуйста: Thread.isMainThread. Но если голова думает, то проще и безопаснее — просто везде использовать async. Зачем тебе этот синхронный вызов, а? Торопишься, блядь, на похороны? Пусть работает асинхронно, и всем хорошо.

Вот и вся мудрость. Не создавай себе проблем на ровном месте, а то охуеешь потом, когда приложение висеть начнёт.