web-dev-qa-db-ja.com

AppleがARCでシングルトンパターンを実装するためにdispatch_onceを使用することを推奨するのはなぜですか?

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の重要なポイントのようです。

なぜ彼らはこれをしているのですか?

301
Proud Member

dispatch_once()は完全に同期しています。すべてのGCDメソッドが非同期的に処理を行うわけではありません(適切な場合、dispatch_sync()は同期的です)。 dispatch_once()を使用すると、次のイディオムが置き換えられます。

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

これに対するdispatch_once()の利点は、高速であることです。また、複数のスレッドがsharedInstanceのalloc initを実行するのを防ぎます(すべてのスレッドが同じ時刻に同時に試行する場合)。 2つのインスタンスを作成することはできません。 dispatch_once()の全体的な考え方は、「一度だけ何かを実行する」ことであり、まさにこれが私たちがやっていることです。

414
Lily Ballard

一度だけ実行されるためです。そのため、異なるスレッドから2回アクセスしようとしても、問題は発生しません。

マイク・アッシュは シングルトンのケアと摂食 ブログ投稿で完全な説明をしています。

すべてのGCDブロックが非同期に実行されるわけではありません。

41
Abizern