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 属性.
我在 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 属性.