Ответ
Оба инструмента синхронизации, но решают разные задачи.
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 потоков одновременно или ждать сигнала | |
| Гибкость | Ноль. Один поток — один ресурс. | Овердохуища. От "жди события" до "пускай не больше пяти". |