В чем разница между NSLock и DispatchSemaphore в iOS?

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

Ответ

Оба инструмента синхронизации, но решают разные задачи.

NSLock (Мьютекс)

  • Назначение: Бинарная блокировка для защиты критической секции (участка кода, который может выполняться только одним потоком одновременно).
  • Принцип: lock()/unlock(). Поток, захвативший блокировку, должен её и освободить.
  • Особенности: Нельзя вызвать unlock() из другого потока. Есть try() для неблокирующей попытки.
    
    let lock = NSLock()
    var sharedArray = [Int]()

func addElement(_ element: Int) { lock.lock() sharedArray.append(element) // Безопасный доступ lock.unlock() }


**DispatchSemaphore (Семафор)**
*   **Назначение:** Контролирует доступ к ресурсу (или группу ресурсов) на основе **счетчика**. Может использоваться для синхронизации и ожидания событий.
*   **Принцип:** `wait()` уменьшает счетчик. Если счетчик < 0, поток блокируется. `signal()` увеличивает счетчик и разблокирует ожидающий поток.
*   **Особенности:** Позволяет ограничить количество одновременных потоков (не только одним).
```swift
// Пример 1: Ограничение параллельных задач (макс. 3)
let semaphore = DispatchSemaphore(value: 3)
for i in 1...10 {
    DispatchQueue.global().async {
        semaphore.wait() // Вход. Если счетчик = 0, ждем.
        downloadLargeFile(id: i)
        semaphore.signal() // Выход
    }
}

// Пример 2: Ожидание завершения асинхронной задачи
let finishSemaphore = DispatchSemaphore(value: 0)
networkService.fetchData { result in
    // Обработка результата
    finishSemaphore.signal() // Сигнализируем о завершении
}
finishSemaphore.wait() // Блокируем текущий поток до получения сигнала
Ключевые отличия: NSLock DispatchSemaphore
Тип Бинарный мьютекс Счетный семафор
Основная цель Защита критической секции Ограничение параллелизма, ожидание событий
Гибкость Один поток на ресурс N потоков на ресурс