Гарантированно ли @synchronized блоки снимают свои блокировки?

#objective-c #macos #cocoa

#objective-c #macos #cocoa

Вопрос:

Предположим, что это методы экземпляра и -run вызывается.

Снимается self ли блокировка к моменту -run возврата?

 ...
- (void)dangerous {
    @synchronized (self) {
        [NSException raise:@"foo" format:@"bar"];
    }
}

- (void)run {
    @try { [self dangerous]; }
    @catch (NSException *ignored) {}
}
...
  

Ответ №1:

@synchronized(obj) { code } Блок фактически эквивалентен

 NSRecursiveLock *lock = objc_fetchLockForObject(obj);
[lock lock];
@try {
    code
}
@finally {
    [lock unlock];
}
  

хотя любой конкретный аспект этого на самом деле является просто деталями реализации. Но да, @synchronized блок гарантированно снимает блокировку независимо от того, как элемент управления выходит из блока.

Комментарии:

1. objc_fetchLockForObject(код) должен быть objc_fetchLockForObject (obj), я полагаю

2. Я надеялся на этот уровень детализации (и думал, что это, вероятно, так). Спасибо!

Ответ №2:

Да, это так.

Блокировка self будет снята после того, как ваш процесс выйдет из @synchronized (self) {} блока.

Ответ №3:

Да, блокировка снимается, когда возвращается -dangerous (даже через исключение). @synchronized добавляет неявный обработчик исключений для освобождения мьютекса.