С какими проблемами сталкивались при работе с потоками
Что проверяют
Знаете ли вы, чем очередь отличается от потока, и умеете ли объяснить, откуда берутся зависания и падения без внятного стека. По ответу видно, писали ли вы многопоточный код сами или всегда обходились готовыми обёртками.
Как отвечать
Соберите ответ вокруг симптомов и их причин:
- замороженный интерфейс.
syncна занятой очереди останавливает вызывающий поток, аDispatchQueue.main.syncиз главного потока это моментальный дедлок, и он же самый частый; - взрыв потоков. Сотни блоков с блокирующими вызовами на конкурентной очереди выедают пул, и приложение встаёт без единой явной блокировки. Лечится ограничителем на семафоре или последовательной очередью;
- гонка данных. Два потока пишут в один словарь, приложение падает внутри рантайма, стек бесполезен. Ловится Thread Sanitizer, закрывается барьером на конкурентной очереди, последовательной очередью или актором;
- современный слой.
asyncиawaitвместо вложенных колбэков,@MainActorна всём, что трогает интерфейс, акторы вместо ручных замков. Мост со старым кодом строится через продолжение, которое обязано быть вызвано ровно один раз; - владение. Блок удерживает
self, и экран не освобождается, пока задача не закончится. Отсюда[weak self]и отмена задач при уходе с экрана.
Где спотыкаются
Пытаются дождаться результата через sync или семафор, лишь бы не переписывать код на колбэки. Получают либо дедлок, либо замороженный интерфейс.
Второе: считают, что последовательная очередь это один и тот же поток. Она гарантирует порядок, но не поток, поэтому рекурсивные замки и данные, привязанные к потоку, ведут себя неожиданно.
Третье: смешивают старую и новую модель. Семафор, ожидающий внутри асинхронной функции, блокирует поток кооперативного пула, а пул этот маленький, и соседние задачи просто перестают выполняться.