帮助理解类方法返回单例 [英] Help understanding class method returning singleton

查看:150
本文介绍了帮助理解类方法返回单例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以帮助我理解以下方法是做什么的?

Can someone please help me understand what the following method is doing?

+ (Game *) shared
{
    static Game *sharedSingleton;

    @synchronized(self)
    {
        if (!sharedSingleton)
        {
            sharedSingleton = [[Game alloc] init];
        }
    }

    return sharedSingleton;
}


推荐答案

显然, singleton是只创建一个实例。实现这个的第一步是通过 static Game * sharedSingleton; 来声明类的静态实例。

Obviously, the idea behind a singleton is to create only a single instance. The first step in achieving this is to declare a static instance of the class via the line static Game *sharedSingleton;.

第二步是检查单个实例是否已经创建,如果不是,则创建它,如果是,则返回现有的单个实例。然而,第二个步骤打开了潜在的问题,在2个单独的线程尝试调用 + shared 方法在同一确切的时刻。你不会希望一个线程修改单个 sharedSingleton 变量,而另一个线程试图检查它,因为它可能会产生意想不到的结果。

The second step is to check whether the single instance is already created, and if it isn't, to create it, or if it is, to return the existing single instance. However, this second step opens up the potential for problems in the event that 2 separate threads try to call the +shared method at the same exact moment. You wouldn't want one thread to be modifying the single sharedSingleton variable while another thread is trying to examine it, as it could produce unexpected results.

这个问题的解决方案是使用 @synchronized()编译器指令来同步访问括号之间指定的对象。例如,假设 Game 类的单个共享实例具有名为 players 的实例变量,它是一个 Player 类的实例的$ c> NSMutableArray 。让我们说 Game 类有一个 -addPlayer:方法,它会修改 / code>实例变量添加指定的播放器。重要的是,如果该方法是从多个线程调用的,那么一次只允许一个线程修改 players 数组。所以,该方法的实现可能看起来像这样:

The solution to this problem is to use the @synchronized() compiler directive to synchronize access to the object specified between the parenthesis. For example, say this single shared instance of the Game class has an instance variable named players which is an NSMutableArray of instances of a Player class. Let's say the Game class had an -addPlayer: method, which would modify the players instance variable by adding the specified player. It's important that if that method were called from multiple threads, that only one thread be allowed to modify the players array at a time. So, the implementation of that method might look something like this:

- (void)addPlayer:(Player *)player {
   if (player == nil) return;
   @synchronized(players) {
      [players addObject:player];
   }
}

使用 @synchronized )指令确保只有一个线程可以一次访问玩家变量。如果一个线程尝试,而另一个线程当前正在访问它,第一个线程必须等待,直到另一个线程完成。

Using the @synchronized() directive makes sure only one thread can access the players variable at a time. If one thread attempts to while another thread is currently accessing it, the first thread must wait until the other thread finishes.

虽然它更直接当你谈论实例变量,它可能不太清楚如何在类本身的单一创建方法中实现相同类型的结果。 @synchronized(self)行中的 self 行基本上等同于 Game 类本身。通过在游戏类上同步,它确保 sharedSingleton = [[Game alloc] init]; 曾经叫过一次。

While it's more straightforward when you're talking about an instance variable, it's perhaps less clear how to achieve the same type of result within the single creation method of the class itself. The self in the @synchronized(self) line in the following code basically equates to the Game class itself. By synchronizing on the Game class, it assures that the sharedSingleton = [[Game alloc] init]; line is only ever called once.

+ (Game *) shared
{
    static Game *sharedSingleton;

    @synchronized(self) // assures only one thread can call [Game shared] at a time
    {
        if (!sharedSingleton)
        {
            sharedSingleton = [[Game alloc] init];
        }
    }

    return sharedSingleton;
}

:已更新。基于我的测试一会儿(我现在刚刚重新测试),以下所有看起来是等效的:

: updated. Based on my tests a while back (and I just re-tested it now), the following all appear to be equivalent:

以外 @implementation

Game *sharedInstance;

@implementation Game
+ (Game *)sharedGame {
    @synchronized(self) {
        if (sharedInstance == nil) {
            sharedInstance = [[[self class] alloc] init];
        }
    }
    return sharedInstance;
}
@end

以外 @implementation static

static Game *sharedInstance;

@implementation Game
+ (Game *)sharedGame {
    @synchronized(self) {
        if (sharedInstance == nil) {
            sharedInstance = [[[self class] alloc] init];
        }
    }
    return sharedInstance;
}
@end

内部 @implementation

@implementation Game

static Game *sharedInstance;

+ (Game *)sharedGame {
    @synchronized(self) {
        if (sharedInstance == nil) {
            sharedInstance = [[[self class] alloc] init];
        }
    }
    return sharedInstance;
}
@end

内部 + sharedGame

@implementation Game
+ (Game *)sharedGame {
    static Game *sharedInstance;
    @synchronized(self) {
        if (sharedInstance == nil) {
            sharedInstance = [[[self class] alloc] init];
        }
    }
    return sharedInstance;
}
@end

唯一的区别是,没有 gdb 中的文件统计信息下不显示 static 关键字, sharedInstance code>。显然,在最后一个变体中, sharedInstance + sharedGame 方法之外不可见。但实际上,他们都确保当你调用 [Game sharedInstance] 时,你会得到 sharedInstance sharedInstance 只创建一次。 (注意,需要进一步的预防措施来防止某人使用 Game * game = [[Game alloc] init]; )创建非singleton实例。

The only difference is that in the first variation, without the static keyword, sharedInstance doesn't show up under File Statics in gdb. And obviously, in the last variation, sharedInstance isn't visible outside of the +sharedGame method. But practically speaking, they all assure that when you call [Game sharedInstance] you'll get back the sharedInstance, and that the sharedInstance is only created once. (Note, however, that further precautions would be needed to prevent someone from creating a non-singleton instance using something like Game *game = [[Game alloc] init];).

这篇关于帮助理解类方法返回单例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆