如何@synchronized锁定/解锁在Objective-C?(How does @synchr

2019-06-17 21:36发布

难道@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];
}

Answer 1:

在Objective-C语言水平同步使用互斥,就像NSLock一样。 从语义上有一些小的技术差异,但基本上是正确的认为它们是在一个共同的(更原始)实体的基础上实现两个独立的接口。

特别是具有NSLock你有一个明确的锁,而与@synchronized你有你使用同步的对象相关的隐式锁。 语言级别锁定的好处是,编译器理解它,所以它可以处理范围的问题,但机械它们的行为基本上是相同的。

你能想到的@synchronized作为一个编译器重写:

- (NSString *)myString {
  @synchronized(self) {
    return [[myString retain] autorelease];
  }
}

转化为:

- (NSString *)myString {
  NSString *retval = nil;
  pthread_mutex_t *self_mutex = LOOK_UP_MUTEX(self);
  pthread_mutex_lock(self_mutex);
  retval = [[myString retain] autorelease];
  pthread_mutex_unlock(self_mutex);
  return retval;
}

这是不完全正确的,因为实际的变换是更复杂,并使用递归锁,但它应该传达出点。



Answer 2:

在Objective-C,一个@synchronized块处理锁定和解锁(以及可能的例外)为您自动。 在运行时动态本质上产生与你同步的对象相关联的NSRecursiveLock。 这苹果文档解释了它的更多细节。 这就是为什么你不能从你的NSLock子看到日志消息 - 您同步的对象可以是任何东西,而不仅仅是一个NSLock。

基本上, @synchronized (...)是一个方便的结构,它简化了你的代码。 最喜欢的简化的抽象,它相关的开销(认为它作为一个隐性成本),它是很好的意识到这一点,但无论如何使用这样的构造时原始性能可能不是最高目标。



Answer 3:

其实

{
  @synchronized(self) {
    return [[myString retain] autorelease];
  }
}

直接转换为:

// needs #import <objc/objc-sync.h>
{
  objc_sync_enter(self)
    id retVal = [[myString retain] autorelease];
  objc_sync_exit(self);
  return retVal;
}

因为iOS版2.0中提供这个API,并采用进口...

#import <objc/objc-sync.h>


Answer 4:

苹果执行@Synchronized是开源的,可以发现在这里 。 迈克灰写了两分关于这个主题真的很有趣的帖子:

  • 锁,线程安全,和斯威夫特
  • 让我们建立@Synchronized

概括地说其具有映射对象指针(利用其存储器地址作为密钥)的表pthread_mutex_t锁,其锁定和解锁根据需要。



Answer 5:

它只是具有相关联的每个对象信号量,并使用该。



文章来源: How does @synchronized lock/unlock in Objective-C?