Что такое семафоры, мьютексы и локи и для чего они нужны
Что проверяют
Понимаете ли вы разницу между примитивами и, главное, знаете ли, какой из них уместен в iOS. Учебник про счётчик и критическую секцию пересказать легко, поэтому интервьюер обычно ждёт продолжения: главный поток, приоритеты и то, что происходит рядом со структурированной конкурентностью.
Как отвечать
Мьютекс это взаимное исключение с владельцем: кто захватил, тот и освобождает. В iOS это NSLock, NSRecursiveLock, pthread_mutex и os_unfair_lock, который пришёл на смену спинлоку именно потому, что сообщает ядру о владельце и гасит инверсию приоритетов.
Семафор это счётчик разрешений без владельца. DispatchSemaphore можно сигналить из другого потока, поэтому он годится и для ограничения параллелизма, и как примитив ожидания события.
Лок это общее слово для взаимного исключения, а не синоним семафора: разница именно во владении, а не в том, что у одного есть счётчик.
Полезно добавить, что в iOS вместо явного лока часто берут последовательную очередь либо барьер в параллельной очереди для схемы с несколькими читателями и одним писателем. В новом коде изоляцию даёт актор, и тогда примитив не нужен вовсе.
Где спотыкаются
Ставят ожидание на семафоре в главном потоке, чтобы дождаться сетевого ответа. Интерфейс замирает, система может снять приложение по сторожевому таймеру, а если ожидаемый блок запланирован в главную очередь, наступает мгновенная взаимная блокировка.
Тащат DispatchSemaphore внутрь асинхронного кода. Пул кооперативного рантайма ограничен числом ядер, заблокированный поток из него не освобождается, и задачи перестают продвигаться. Ждать нужно через await, а колбэк заворачивать в продолжение.
Считают лок реентерабельным. Повторный захват NSLock из того же потока это гарантированный дедлок. NSRecursiveLock спасает, но обычно это сигнал, что критическая секция вызывает чужой код и её пора сократить.