Что такое SpinLock в контексте многопоточности?

«Что такое SpinLock в контексте многопоточности?» — вопрос из категории Многопоточность, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

SpinLock (спин-лок, блокировка с активным ожиданием) — это низкоуровневый примитив синхронизации, при котором поток, не получивший блокировку, не переходит в состояние ожидания (sleep), а продолжает активно опрашивать ("крутиться" в цикле) её доступность.

Принцип работы: Пока один поток удерживает блокировку, другие потоки в цикле проверяют её освобождение, потребляя процессорное время.

Критические недостатки на iOS/macOS:

  • Приоритетная инверсия: Высокоприоритетный поток может бесконечно ждать низкоприоритетный, удерживающий блокировку, что приводит к deadlock. Из-за этого OSSpinLock был объявлен deprecated.
  • Растрата CPU: Неэффективен для длительных операций.

Современная альтернатива в Apple экосистеме — os_unfair_lock:

import os

class ThreadSafeCounter {
    private var lock = os_unfair_lock()
    private var count = 0

    func increment() {
        os_unfair_lock_lock(&lock)
        defer { os_unfair_lock_unlock(&lock) }
        count += 1
    }
}

Когда использовать? Только для крайне коротких критических секций (несколько инструкций), где накладные расходы на переключение контекста больше, чем время "спина". В большинстве случаев лучше использовать высокоуровневые API: DispatchQueue, NSLock или акторы (actor) в Swift.