- (NSHashTable *)pollers
{
if (!_pollers) {
dispatch_sync(self.serialQueue, ^{
_pollers = [NSHashTable weakObjectsHashTable];
});
}
return _pollers;
}
pollers是单例上的非原子属性。在单例中还有一些其他方法,其中将对象添加到轮询器中,并且我使用@synchronized作为其添加([self.pollers addObject:____])。
无论如何......我对上面的代码有疑问。如果2个线程同时调用此函数,则它们都可以通过if (!_pollers)
代码,然后两个代码将在我们的自定义serialQueue上同步调度_pollers = [NSHashTable weakObjectsHashTable];
代码。所以我们实际上会运行两次代码。
有更好的方法吗?
答案 0 :(得分:0)
像这样使用dispatch_once
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
dispatch_sync(self.serialQueue, ^{
_pollers = [NSHashTable weakObjectsHashTable];
});
});
return pollers;
答案 1 :(得分:0)
此
只需要一个dispatch_once
功能
您的串行队列现在是冗余的,因为dispatch_once
将确保仅调用一次块(即使从多个线程同时调用)contrary to what pds says。
The documentation clearly states that:
如果从多个线程同时调用[dispatch_once],此函数将同步等待,直到块完成。
您的if
声明也是多余的as pointed out by Josh。
因此您只想:
- (NSHashTable *)pollers
{
static dispatch_once_t t;
dispatch_once(&t, ^{
_pollers = [NSHashTable weakObjectsHashTable];
});
return _pollers;
}
值得注意的是,您需要一个线程安全的单例sharedInstance
实现,以使其具有防弹性能。您可以使用dispatch_once
以相同的方式执行此操作。例如:
static singleton* sharedInstance;
+(instancetype) sharedInstance {
static dispatch_once_t t;
dispatch_once(&t, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}