В чем разница между NSLock и DispatchSemaphore в 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 потоков на ресурс

Ответ 18+ 🔞

Слушай, ну вот реально, люди путают их постоянно, а это же как сравнивать молоток и швейцарский нож — оба железные, но задачи-то, блядь, разные, ёпта!

NSLock — это такой упоротый привратник

  • Суть его жизни: стоять у одной-единственной двери в критическую секцию и не пускать туда никого, пока нынешний посетитель не выйдет. Вообще никого. Один поток — один доступ.
  • Как работает: lock() — захлопнул дверь, unlock() — открыл. И главное, блядь, правило: кто закрыл, тот и открывает. Нельзя из другого потока крикнуть "эй, открой уже!" — не сработает. Есть try() — типа вежливо постучаться, не получилось — пошёл нахуй, не будешь ждать.
    
    let lock = NSLock()
    var sharedArray = [Int]()

func addElement(_ element: Int) { lock.lock() // Всё, я здесь, все ждите sharedArray.append(element) // Делаю свои делишки lock.unlock() // Всё, свободен, следующий! }


**DispatchSemaphore — это хитрая турникетная система**
*   **Суть:** у него есть счётчик, блядь, как билеты в кино. **Ресурсов может быть несколько** (например, 3 потока одновременно), или он может вообще использоваться для сигналов "событие произошло".
*   **Как работает:** `wait()` — взял билетик (счётчик минус). Билеты кончились (счётчик ноль)? Сиди, жди, пока кто-то не сдаст свой. `signal()` — сдал билет (счётчик плюс), турникет пропускает следующего.
*   **И вот где, сука, мощь:** им можно и очередь ограничить, и дождаться чего-то асинхронного.

```swift
// Пример 1: Не больше трёх качалок одновременно, а то сервер ебнётся
let downloadSemaphore = DispatchSemaphore(value: 3) // Три билета
for i in 1...10 {
    DispatchQueue.global().async {
        downloadSemaphore.wait() // Билет есть? Беру. Нет? Стою, блядь.
        downloadHeavyFile(id: i) // Качаю
        downloadSemaphore.signal() // Всё, отдаю билет обратно!
    }
}

// Пример 2: Классика: "Подожди тут, я схожу в сеть, вернусь — свистну"
let finishSemaphore = DispatchSemaphore(value: 0) // Билетов изначально НОЛЬ!
someAsyncTask { result in
    // Делаю что-то долгое...
    finishSemaphore.signal() // Всё, свистнул, положил один билетик в турникет
}
// Главный поток:
finishSemaphore.wait() // Стою у пустого турникета, жду билетика. Получил — пошёл дальше.
Короче, итоговая разница, чтоб в рот мне чих-пых: NSLock DispatchSemaphore
Что он такое Тупая железная дверь с одним ключом Умный турникет с ограниченным числом пропусков
Зачем нужен Чтобы только один поток в один момент времени что-то делал Чтобы пускать N потоков одновременно или ждать сигнала
Гибкость Ноль. Один поток — один ресурс. Овердохуища. От "жди события" до "пускай не больше пяти".