Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Реализация Semaphore в iOS
Semaphore это примитив синхронизации для управления доступом к ограниченному ресурсу. Я часто использую его для контроля параллельных операций.
Основная идея
Semaphore поддерживает счетчик:
- signal() — увеличивает счетчик (освобождает ресурс)
- wait() — уменьшает счетчик (занимает ресурс)
- Если счетчик = 0, поток блокируется до signal()
Использование в iOS
Dispatch Semaphore реализован в Darwin kernel:
import Dispatch
let semaphore = DispatchSemaphore(value: 3)
if semaphore.wait(timeout: .now() + 10) == .timedOut {
print("Timeout!")
}
semaphore.signal()
Ограничение параллельных операций
Основное применение — контроль одновременных задач:
func downloadImages(urls: [URL]) async {
let semaphore = DispatchSemaphore(value: 3)
let queue = DispatchQueue.global()
for url in urls {
queue.async {
semaphore.wait()
defer { semaphore.signal() }
let _ = try? Data(contentsOf: url)
print("Downloaded")
}
}
}
Синхронизация async/await
Semaphore полезен для синхронизации async операций:
func fetchDataSequentially() async {
let semaphore = DispatchSemaphore(value: 1)
let task1 = Task {
semaphore.wait()
defer { semaphore.signal() }
let data = try await fetchUserData()
}
await task1.value
}
Внутренняя реализация
Внутри Darwin kernel используются:
- Atomic операции для изменения счетчика
- Futex для эффективной блокировки потоков
- Очередь ожидающих потоков для справедливого распределения
Практические применения
1. Ограничение сетевых запросов:
class APIClient {
private let semaphore = DispatchSemaphore(value: 5)
func request<T: Decodable>(_ endpoint: String) async throws -> T {
semaphore.wait()
defer { semaphore.signal() }
let url = URL(string: endpoint)!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode(T.self, from: data)
}
}
2. Очередь обработки задач:
class TaskProcessor {
private let semaphore = DispatchSemaphore(value: 1)
func processTask(_ task: Task) {
semaphore.wait()
defer { semaphore.signal() }
task.execute()
}
}
Важные особенности
- Не может быть отрицательным — счетчик ниже нуля невозможен
- FIFO очередь — потоки просыпаются в порядке очереди
- Deadlock риск — нужна аккуратность с зависимостями
- Timeout поддержка — можно установить максимальное время
Когда использовать
- Контроль параллельных операций
- Синхронизация между потоками
- Ограничение доступа к ресурсам
- Реализация producer-consumer паттерна
Semaphore это мощный инструмент для управления параллелизмом.