我怎样才能多线程创建延迟加载 属性?

How can I multithread the creation of a lazily loaded property?

 - (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]; 代码。所以我们实际上 运行 代码两次。

有更好的方法吗?

像这样使用dispatch_once

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
  dispatch_sync(self.serialQueue, ^{
    _pollers = [NSHashTable weakObjectsHashTable];
  });
});
return pollers;

为此你只需要一个dispatch_once函数

您的串行队列现在是多余的,因为 dispatch_once 将确保该块仅被调用一次(即使从多个线程同时调用),.

The documentation clearly states that:

If [dispatch_once is] called simultaneously from multiple threads, this function waits synchronously until the block has completed.

你的if说法也是多余的,

因此你只需要:

- (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;
}