Вопрос проверяет понимание различий между высокоуровневыми и низкоуровневыми примитивами синхронизации в iOS.
NSLock — это объектная обёртка над mutex, предназначенная для взаимного исключения. Semaphore — более универсальный примитив, работающий на основе счётчика. NSLock всегда пускает только один поток в критическую секцию, semaphore может пускать несколько. NSLock проще и безопаснее для защиты данных. Semaphore чаще используется для координации потоков и ограничения параллелизма.
Хотя NSLock и DispatchSemaphore часто применяются для похожих задач, они решают их на разных уровнях абстракции и с разной семантикой.
NSLock — это объект синхронизации, обеспечивающий взаимное исключение доступа к ресурсу одним потоком.
Перед списком важно понимать, что NSLock концептуально — это mutex.
В критическую секцию может войти только один поток
Поток, захвативший lock, обязан его освободить
Поддерживает методы lock(), unlock(), try()
Предназначен именно для защиты общих данных
let lock = NSLock()
lock.lock()
// работа с общими данными
lock.unlock()
Semaphore работает иначе и решает более широкий круг задач.
Основан на счётчике, а не на владении
Может пускать несколько потоков одновременно
signal() может быть вызван другим потоком
Используется для ограничения количества задач или ожидания событий
let semaphore = DispatchSemaphore(value: 3)
NSLock:
защита состояния объектов
работа с разделяемыми данными
простой и понятный сценарий
Semaphore:
ограничение параллельных операций
ожидание завершения асинхронной задачи
координация нескольких очередей
NSLock — правильный выбор для защиты данных. Semaphore — мощный, но более опасный инструмент, который стоит использовать только при необходимости управления параллелизмом.