Objective-C 中的线程安全单例 syncd()



在我们的应用程序中,我们在多个位置使用单例,最近我浏览并添加了@synchronized命令到所有单例方法中,以确保它们是线程安全的。我的问题是,这两者之间有什么区别:

+ (RLReceiver *) getReceiver
{
    static RLReceiver *receiverCache;
    @synchronized(receiverCache)
    {
        if (!receiverCache )
            receiverCache = [[RLReceiver alloc] init];
        return receiverCache;
    }
}

在这种情况下,我同步了类RLReceiver的静态实例,但我也看到了(编译器令人惊讶地允许)这一点:

+ (RLReceiver *) getReceiver
{
    static RLReceiver *receiverCache;
    @synchronized(self)
    {
        if (!receiverCache )
            receiverCache = [[RLReceiver alloc] init];
        return receiverCache;
    }
}

同步在self 上的位置。这让我有点困惑,因为此方法是一个类方法,在此方法的这个范围内甚至不应该有self。谁能阐明在这种情况下静态变量和 self 之间的区别是什么,以及类方法中如何存在 self?

根据Apple Doc:"传递给@synchronized指令的对象是用于区分受保护块的唯一标识符。如果在两个不同的线程中执行上述方法,在每个线程上为 anObj 参数传递不同的对象,则每个线程都将获取其锁并继续处理,而不会被另一个线程阻止。但是,如果在这两种情况下都传递相同的对象,则其中一个线程将首先获取锁,另一个线程将阻塞,直到第一个线程完成关键部分。

苹果的例子:

- (void)myMethod:(id)anObj
{
@synchronized(anObj)
{
    // Everything between the braces is protected by the @synchronized directive.
}
}

在您的情况下,Hot Licks 如何说问题是第一次发射。您的对象在首次启动中不存在,并且同步的无法正常工作。如果您尝试:

[1]

 +(RLReceiver *) getReceiver
{
static RLReceiver *receiverCache;
@synchronized(receiverCache)
{
    if (!receiverCache ) {
        receiverCache = [[RLReceiver alloc] init];
    }
    for (int i=0; i<100; i++) {
        NSLog(@"Numbers in order i %i",i);
    }
    return receiverCache;
}
} 

和 [2]

+ (RLReceiver *) getReceiver
{
static RLReceiver *receiverCache;
@synchronized(self)
{
    if (!receiverCache ) {
        receiverCache = [[RLReceiver alloc] init];
    }
    for (int i=0; i<100; i++) {
        NSLog(@"Numbers in order i %i",i);
    }
    return receiverCache;
}
}

从另一个对象第一次调用类似的东西:

    dispatch_async(dispatch_queue_create("OtherQueue", 0), ^{
RLReceiver *rece= [RLReceiver getReceiver];
});
RLReceiver *receSorF = [RLReceiver getReceiver];

您可以看到在 [1] 情况下,数字混合和同步不起作用。在 [2] 的情况下,一个计数等待另一个计数。

当我们同步现有对象中的代码时,我们可以使用该对象,在其他情况下是类名。

谢谢@HotLicks。

最新更新