1. ホーム
  2. アイオス

[解決済み】AppleがARCでのシングルトンパターンの実装にdispatch_onceの使用を推奨するのはなぜですか?

2022-03-28 14:14:46

質問

ARCのシングルトンの共有インスタンスアクセッサでdispatch_onceを使用する正確な理由は何でしょうか?

+ (MyClass *)sharedInstance
{
    //  Static local predicate must be initialized to 0
    static MyClass *sharedInstance = nil;
    static dispatch_once_t onceToken = 0;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[MyClass alloc] init];
        // Do any other initialisation stuff here
    });
    return sharedInstance;
}

シングルトンをバックグラウンドで非同期にインスタンス化するのはまずいのでは?つまり、私がその共有インスタンスを要求し、すぐにそれに頼ったとしても、 dispatch_once が私のオブジェクトを作成するためにクリスマスまでかかったらどうなるのでしょうか?それはすぐに返されないのですね?少なくとも、それがGrand Central Dispatchの全体的なポイントであるように思えます。

では、なぜこのようなことをするのでしょうか?

どうすれば解決するの?

dispatch_once() は絶対に同期です。すべてのGCDメソッドが非同期で物事を行うわけではありません(例. dispatch_sync() は同期です)。の使用は dispatch_once() は、以下のイディオムに置き換わります。

+ (MyClass *)sharedInstance {
    static MyClass *sharedInstance = nil;
    @synchronized(self) {
        if (sharedInstance == nil) {
            sharedInstance = [[MyClass alloc] init];
        }
    }
    return sharedInstance;
}

のメリットは dispatch_once() よりも速いということです。また、複数のスレッドが同時にsharedInstanceのalloc initを実行するのを防げるので、意味的にもすっきりしています。2つのインスタンスを作成することはできません。の全体の考え方は dispatch_once() というのは、一度だけ何かを実行し、一度だけしか実行しないということで、まさに私たちがやっていることはそれです。