6

たくさんの読み取り(新しいアイテムが到着した)の後に一度変更される可変配列を使用するクラスがあります。

問題は、配列を変更するときが来ると、読み取りが継続して行われることです。

現在、何かを読み取るたびにこの問題を回避するために、コピーを介して読み取ります。

[[theArray copy] operation] //operation being indexOfObject:, objectAtIndex: objectsAtIndexes:, etc.

特に必要がない場合(アレイが変更されていない場合)、コピーは非常に高価になります。

変異しているときにアレイへのアクセスを遅らせるためにアレイをロックするにはどうすればよいですか?

4

3 に答える 3

10

すべての配列アクセスをシリアルディスパッチキューに入れます。これにより、2つの操作が同時に発生するのを防ぐことができます。『同時実行プログラミングガイド』の「ロックベースのコードの削除」を参照してください。

iOS> = 4.3が必要な場合は、同時カスタムキューを使用して、ミューテーション操作にバリアをディスパッチできます。これにより、読み取りを同時に行うことができますが、書き込みが必要な場合は、書き込みが完了するまで保持されます。バリアとして送信されたブロックは、基本的に並行キューでシリアルに実行されます。前のすべてのブロックが終了するまで開始されません。また、バリアブロックが完了するまで後続のブロックも開始されません。(これは、ジャスティンが言及している読み取り/書き込みロックのGCDバージョンです。)このサンプルについては、他に類を見ないマイクアッシュを紹介します。

于 2012-08-09T19:29:38.117 に答える
5

最も簡単なアプローチは@synchronized、次のように使用することです。

-(void) accessTheArray {
    MyClass *obj;
    @synchronized(theArray) {
        obj = [theArray objectAtIndex:...];
    }
    [obj someMessage];
}

編集: ARCを使用していない場合は、オブジェクトを保持/自動解放することをお勧めします。そうしないと、呼び出される前に配列から削除(および解放)される可能性があります(この優れたコメントを提供してくれたomzsomeMessageに感謝します)。

于 2012-08-09T19:25:44.193 に答える
2

この場合、読み取り/書き込みロックの使用を検討します。Cocoaはそれらを提供しませんが、でpthread_rwlock_t宣言されているpthreadsインターフェースで使用できますpthread.h@synchronizedこれは、(使用法にとって) 、または単純なロックよりもはるかに効率的であることに注意してください。

于 2012-08-09T19:25:28.680 に答える