Xcode 中具有 atomic/synchronized 属性和 NSLock 的线程清理器问题

Thread sanitizer issue in Xcode with atomic/synchronized properties & NSLock

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

@property (atomic, strong) NSNumber *validLock;

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

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

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

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

尽管采取了所有这些预防措施,Xcode 中的线程清洁程序仍然在 @synchronized getter 行中断并带有注释 "Data Race detected."

我什至放弃了“@synchronized”的想法,全力投入 NSLock 但无济于事。

这变得很可笑,因为这也被 Xcode 线程清理器标记在 [myLock lock] 上:

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

我做错了什么?

这不是特别有意义:

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

我认为您希望它在 "the validLock property of self" 上同步,但这不是参数的含义。您正在同步当前由 validLock 指向的 NSNumber(您随后替换的 NSNumber)。由于这与您在其他地方同步的对象不同,因此作用不大。

同样,如果这段代码都在同一个上下文中(这是你的例子所暗示的),它也不会做任何事情:

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

每个线程都有自己的锁。

首先,您确实要避免 NSLock@synchronized。它们已被 GCD 取代多年。有关详细信息,请参阅 Concurrency Programming Guide

如果您真的想使用 @synchronized(意识到它非常不灵活且非常慢),那么通常您会在 self.

上调用它
@synchronized(self) {
   self.validLock = @YES;
}

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

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