代码之家  ›  专栏  ›  技术社区  ›  zzyzy

带有原子/同步属性和NSLock的Xcode中的线程清洗程序问题

  •  0
  • zzyzy  · 技术社区  · 6 年前

    我在Objective-C中的一个对象上声明了一个属性,该对象是从多个线程调用的:

    @property (atomic, strong) NSNumber *validLock;

    @synchronized(self.validLock) {
       self.validLock = @YES;
    }
    

    在我的getter中,我执行以下操作:

    @synchronized(self.validLock) {
       if (self.validLock.boolValue) {
          ...
       }
    }
    

    尽管有这些预防措施,Xcode中的线程消毒器仍然会在 @synchronized getter行中带有注释“检测到数据竞争”

    我甚至放弃了“@synchronized”的想法,全力以赴 NSLock

    [myLock lock] 通过Xcode线程消毒器:

    NSLock *myLock = [[NSLock alloc] init];
    ...
    [myLock lock];
    self.validLock = @NO;
    [myLock unlock];
    

    我做错什么了?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Rob Napier    6 年前

    这不是特别有意义:

    @synchronized(self.validLock) {
       self.validLock = @YES;
    }
    

    我想你希望这个能在“the validLock 财产 self “但参数不是这个意思。你正在同步 NSNumber 有效锁定 数字对象 然后替换)。因为这不是您在其他地方同步的对象,所以这没有什么作用。

    NSLock *myLock = [[NSLock alloc] init];
    ...
    [myLock lock];
    self.validLock = @NO;
    [myLock unlock];
    

    每个线程都有自己的锁。

    NSLock @synchronized . 他们已经被GCD取代很多年了。看到了吗 Concurrency Programming Guide 完整的细节。

    如果你真的想用 (意识到这是相当不灵活和相当缓慢),然后通常你呼吁它 .

    @synchronized(self) {
       self.validLock = @YES;
    }
    

    但无论如何,它必须在同一个实际对象上(而不仅仅是同一个对象的名称)。

    如果你要用 ,您需要确保每个人都共享相同的实际锁,因此对于单个实例,它必须是一个属性。对于多个实例,它需要是全局属性或至少是类属性。