首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >目标C中线程安全的Singleton ()

目标C中线程安全的Singleton ()
EN

Stack Overflow用户
提问于 2015-01-30 18:09:59
回答 1查看 1.7K关注 0票数 1

在我们的应用程序中,我们在几个位置使用单例,最近我完成了在所有单例方法中添加@synchronized命令,以确保它们是线程安全的。我的问题是,把这称为“这样”有什么区别:

代码语言:javascript
复制
+ (RLReceiver *) getReceiver
{
    static RLReceiver *receiverCache;
    @synchronized(receiverCache)
    {
        if (!receiverCache )
            receiverCache = [[RLReceiver alloc] init];
        return receiverCache;
    }
}

在本例中,我同步了类RLReceiver的静态实例,但我也看到(编译器出人意料地允许)这样做:

代码语言:javascript
复制
+ (RLReceiver *) getReceiver
{
    static RLReceiver *receiverCache;
    @synchronized(self)
    {
        if (!receiverCache )
            receiverCache = [[RLReceiver alloc] init];
        return receiverCache;
    }
}

同步在self上的位置。这让我有点困惑,因为这个方法是一个类方法,而且在这个方法的范围内甚至不应该有一个self。有人能解释一下静态变量和自我在这个上下文中的区别,以及类方法中的自我是如何存在的吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-01-30 18:23:18

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

// Apple示例:

代码语言:javascript
复制
- (void)myMethod:(id)anObj
{
@synchronized(anObj)
{
    // Everything between the braces is protected by the @synchronized directive.
}
}

在你的例子中,辣妹说问题是第一次发射。您的对象在第一次启动时不存在,同步也不能正常工作。如果你尝试:

1

代码语言:javascript
复制
 +(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

代码语言:javascript
复制
+ (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;
}
}

来自第一次调用的另一个对象,类似于:

代码语言:javascript
复制
    dispatch_async(dispatch_queue_create("OtherQueue", 0), ^{
RLReceiver *rece= [RLReceiver getReceiver];
});
RLReceiver *receSorF = [RLReceiver getReceiver];

您可以看到,在1种情况下,数字是如何混合的,并且同步是如何工作的。在2种情况下,一位伯爵等待另一位伯爵。

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

谢谢@HotLick。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28242063

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档