@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];
}
5 回答
Objective-C语言级同步使用互斥锁,就像
NSLock
一样 . 从语义上讲,存在一些小的技术差异,但将它们视为在公共(更原始)实体之上实现的两个独立接口基本上是正确的 .特别是对于
NSLock
,您有一个显式锁,而对于@synchronized
,您有一个与您用于同步的对象关联的隐式锁 . 语言级别锁定的好处是编译器能够理解它,因此它可以处理范围问题,但机械上它们的行为基本相同 .您可以将
@synchronized
视为编译器重写:转化为:
这不完全正确,因为实际的转换更复杂并使用递归锁,但它应该得到重点 .
在Objective-C中,
@synchronized
块会自动为您处理锁定和解锁(以及可能的异常) . 运行时动态地生成一个NSRecursiveLock,它与您正在同步的对象相关联 . This Apple documentation更详细地解释了它 . 这就是为什么你没有看到NSLock子类的日志消息 - 你同步的对象可以是任何东西,而不仅仅是一个NSLock .基本上,
@synchronized (...)
是一种简化代码的便捷结构 . 像大多数简化的抽象一样,它具有相关的开销(将其视为隐藏成本),并且很好地意识到这一点,但是无论如何使用这样的构造时,原始性能可能不是最高目标 .其实
直接转换为:
此API自iOS 2.0起可用并使用...
Apple的@synchronized实现是开源的,可以找到here . Mike Ash写了两篇关于这个主题的非常有趣的帖子:
Locks, Thread Safety, and Swift
Let's Build @synchronized
简而言之,它有一个表,用于将对象指针(使用其内存地址作为键)映射到
pthread_mutex_t
锁,这些锁根据需要锁定和解锁 .它只是将信号量与每个对象相关联,并使用它 .