Комментарии (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 это мощный инструмент для управления параллелизмом.
Похожие вопросы
- Что такое ООП?
- Зачем нужен виртуальный деструктор?
- Какие источники использовал для обучения?
- Со своей ли техникой нужно работать
- Чем отличается malloc от new в C++?
- В чем разница между ссылкой и указателем?
- Что такое input/output?
- Что критично в новой работе?
- Что вернет функция std::find_if в случае неудачного поиска?
- Опишите TCP 3-way handshake.
- Что происходит при выбрасывании исключения из конструктора?
- В каких командах работал
- Как передать параметр в функцию?
- Как послать сигнал процессу?
- Как нравится работать больше: в одиночку или в команде?
- Что такое shared_ptr?
- Что такое процесс?
- Какие требования к новой работе?
- Зачем нужен указатель?
- Какие знаешь виды наследования классов?