На каких низкоуровневых примитивах построены механизмы блокировок (локи) в iOS?

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

Ответ

Высокоуровневые API синхронизации (такие как NSLock или @synchronized) базируются на примитивах ядра Darwin (XNU):

  1. POSIX-мьютексы (pthread_mutex_t) — основа для NSLock и реализации @synchronized.
  2. Спинлоки (os_unfair_lock) — легковесные нереентерабельные блокировки. С iOS 10 NSLock внутри использует os_unfair_lock.
  3. Семафоры (dispatch_semaphore_t, sem_t) — для управления доступом к ресурсу с ограниченной емкостью или сложной синхронизации.
  4. Атомарные операции (CAS — Compare-And-Swap) — лежат в основе atomic-свойств и многих lock-free структур данных.

Пример низкоуровневой реализации с pthread_mutex_t:

#include <pthread.h>
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);

pthread_mutex_lock(&mutex);
// Критическая секция — доступ к общему ресурсу
pthread_mutex_unlock(&mutex);

pthread_mutex_destroy(&mutex);

Примечание: @synchronized(obj) использует objc_sync_enter(obj) и objc_sync_exit(obj), которые работают через хеш-таблицу мьютексов, ассоциированных с объектами.