Когда следует использовать Semaphore в iOS?

«Когда следует использовать Semaphore в iOS?» — вопрос из категории Многопоточность, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Semaphore (DispatchSemaphore) используется для ограничения количества одновременных операций, обращающихся к общему ресурсу с ограниченной ёмкостью.

Типичные сценарии:

  • Rate limiting API-запросов — чтобы не превысить лимиты сервера.
  • Ограничение параллельных файловых операций или сетевых соединений.
  • Синхронизация доступа к ресурсу, когда DispatchQueue или OperationQueue недостаточно гибки.

Пример (Swift):

// Ограничиваем максимум 3 одновременные задачи
let semaphore = DispatchSemaphore(value: 3)

for i in 1...10 {
    DispatchQueue.global().async {
        semaphore.wait() // Запрашиваем доступ
        defer { semaphore.signal() } // Гарантированно освобождаем

        // Критическая секция: работа с ограниченным ресурсом
        print("Задача (i) выполняется")
        Thread.sleep(forTimeInterval: 1)
    }
}

Важные предостережения:

  1. Всегда используйте defer { semaphore.signal() } или аналогичный механизм, чтобы избежать deadlock.
  2. Никогда не вызывайте wait() на главном потоке — это заблокирует UI.
  3. Для большинства задач синхронизации предпочтительнее серийные очереди (DispatchQueue) или OperationQueue с установленным maxConcurrentOperationCount.