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


305

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がクリスマスまで私のオブジェクトを作成するとしたらどうなるでしょうか。すぐ戻りませんよね?少なくともそれがグランドセントラルディスパッチの要点のようです。

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


Note: static and global variables default to zero.
ikkentim 2016

回答:


418

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()は、それがより速いということです。また、共有インスタンスのalloc initを実行する複数のスレッドからも保護されるため、意味的にクリーンです。2つのインスタンスを作成することはできません。の全体的な考え方dispatch_once()は「一度だけ実行すること」であり、それがまさに私たちがやっていることです。


4
議論のために、私はドキュメントが同期的に実行されているとは述べていないことに注意する必要があります。複数の同時呼び出しがシリアル化されることだけを示しています。
エキスパート

5
あなたはそれがより速いと主張しています-どのくらい速いのですか?あなたが本当のことを言っていないと思う理由はありませんが、簡単なベンチマークが欲しいです。
Joshua Gross 2013年

29
(iPhone 5で)単純なベンチマークを実行したところ、dispatch_onceは@synchronizedよりも約2倍高速であるように見えます。
ジョシュアグロス

3
@ReneDohan:誰もそのメソッドを別のスレッドから呼び出さないことが100%確実であれば、それは機能します。ただし、使用dispatch_once()は非常に簡単であり(特にXcodeが完全なコードスニペットにオートコンプリートするため)、メソッドをスレッドセーフにする必要があるかどうかを考慮する必要もありません。
リリーバラード

1
@siuying:実はそうではありません。まず、+initialize共有インスタンスをまだ作成していない場合でも、クラスに触れる前に行われる処理が行われます。一般に、遅延初期化(必要なときにのみ何かを作成する)の方が優れています。第二に、あなたのパフォーマンスの主張でさえ真実ではありません。dispatch_once()言うように、時間のほぼ正確に同じ量を取るif (self == [MyClass class])+initialize。すでにがある場合+initialize、共有インスタンスを作成すると高速になりますが、ほとんどのクラスにはありません。
リリーバラード

41

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

Mike Ashは、彼のCare and Feeding of Singletonsブログ投稿に詳しい説明があります。

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


Lily'sの方が良い答えですが、Mike Ashの投稿へのリンクを維持するために私は離れます。
アビゼル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.