Разве @synchronized не использует «блокировку» и «разблокировку» для достижения взаимного исключения? Как это делает блокировку / разблокировку тогда?
Вывод следующей программы - только «Hello World».
@interface MyLock: NSLock<NSLocking>
@end
@implementation MyLock
- (id)init {
return [super init];
}
- (void)lock {
NSLog(@"before lock");
[super lock];
NSLog(@"after lock");
}
- (void)unlock {
NSLog(@"before unlock");
[super unlock];
NSLog(@"after unlock");
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
MyLock *lock = [[MyLock new] autorelease];
@synchronized(lock) {
NSLog(@"Hello World");
}
[pool drain];
}
objective-c
synchronization
Дэвид Лин
источник
источник
lock
Объект создается при каждом вызове, так что никогда не будет случай , когда один@synchronized
блок блокирует другой. И это означает, что взаимного исключения не существует.) Конечно, в приведенном выше примере выполняется операцияmain
, поэтому в любом случае исключать нечего, но не следует слепо копировать этот код в другом месте.Ответы:
Синхронизация на уровне языка Objective C использует мьютекс, как и
NSLock
делает. Семантически существуют некоторые небольшие технические различия, но в основном правильно думать о них как о двух отдельных интерфейсах, реализованных поверх общей (более примитивной) сущности.В частности, у
NSLock
вас есть явная блокировка, тогда как у@synchronized
вас есть неявная блокировка, связанная с объектом, который вы используете для синхронизации. Преимущество блокировки на уровне языка заключается в том, что компилятор понимает ее, поэтому он может решать проблемы с областями видимости, но механически они ведут себя в основном одинаково.Вы можете думать
@synchronized
как о переписывании компилятора:превращается в:
Это не совсем правильно, потому что фактическое преобразование является более сложным и использует рекурсивные блокировки, но оно должно понять смысл.
источник
В Objective-C
@synchronized
блок обрабатывает блокировку и разблокировку (а также возможные исключения) автоматически. Среда выполнения динамически по существу генерирует NSRecursiveLock, который связан с объектом, с которым вы синхронизируете. Эта документация Apple объясняет это более подробно. Вот почему вы не видите сообщений журнала от вашего подкласса NSLock - объект, с которым вы синхронизируете, может быть чем угодно, не только NSLock.По сути,
@synchronized (...)
это удобная конструкция, которая упрощает ваш код. Подобно большинству упрощенных абстракций, он связан с накладными расходами (воспринимается как скрытая стоимость), и это хорошо осознавать, но в любом случае необработанная производительность, вероятно, не является высшей целью при использовании таких конструкций.источник
Фактически
превращается непосредственно в:
Этот API доступен начиная с iOS 2.0 и импортирован с использованием ...
источник
@synchronized
блок неявно добавляет обработчик исключений в защищенный код. Этот обработчик автоматически освобождает мьютекс в случае возникновения исключения».Реализация @synchronized от Apple является открытым исходным кодом, и ее можно найти здесь . Майк Эш написал два действительно интересных поста на эту тему:
В двух словах, у него есть таблица, которая отображает указатели объектов (используя их адреса памяти в качестве ключей) для
pthread_mutex_t
блокировок, которые блокируются и разблокируются по мере необходимости.источник
Он просто связывает семафор с каждым объектом и использует его.
источник