← Назад к вопросам

Почему ищешь новую работу?

1.0 Junior🔥 241 комментариев
#Soft skills и мотивация

Комментарии (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 это мощный инструмент для управления параллелизмом.