Как работает директива @synchronized для метода в Objective-C?

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

Ответ

Директива @synchronized в Objective-C создает взаимное исключение (mutex) на основе переданного объекта-монитора. Когда она применяется к методу, этот метод становится критической секцией.

Принцип работы:

  1. Для обычного метода монитором выступает сам экземпляр объекта (self).
  2. Для статического (классового) метода монитором выступает объект класса.
  3. При входе в метод поток захватывает блокировку монитора.
  4. Если другой поток попытается войти в любой метод этого же экземпляра (или класса), защищенный @synchronized с тем же монитором, он будет заблокирован до освобождения монитора первым потоком.

Пример в Objective-C:

- (void)threadSafeMethod {
    @synchronized(self) { // Блокировка на объекте 'self'
        // Критическая секция.
        // Только один поток может выполнять этот код для данного 'self'.
        [self modifySharedResource];
    } // Блокировка автоматически снимается здесь
}

Важные нюансы и аналоги в Swift:

  • Уровень блокировки — объект, а не метод. Два разных метода, синхронизированные по self, также будут блокировать друг друга.
  • Риск взаимной блокировки (deadlock): Если два потока захватывают мониторы A и B в разном порядке.
  • В Swift нет прямой аналогии @synchronized. Вместо нее используют:
    • DispatchQueue с атрибутом .serial и барьерами (для чтения/записи).
    • NSLock, os_unfair_lock для точечной синхронизации.
    • Акторы (Actors) — современный Swift-способ изоляции состояния.