2012-08-09 3 views
5

私は多くの読み込み(新しい項目が到着)の後に一度変更される可変配列を使用するクラスを持っています。NSMutableArrayをコピーしてマルチスレッドの書き込みでコピーしないようにします

問題は、時間がアレイを突然変異させるようになると、読み取りが継続することです。

現在、この問題にそれはそれはそうコピーの上にない何か読み込むたび避けるために:配列である(これらすべての回に必要がない場合は特に

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

コピーは、本当に高価になってきているが変異していない)。

突然変異している場合、配列へのアクセスを遅らせるために配列をロックするにはどうすればよいですか?

+0

この配列をクラスのプロパティとして作成し、宣言時にアトミックにしないと、コンパイラはスレッド間であらゆる種類の同期を処理します。 – kidsid49

答えて

9

すべてのアレイアクセスをシリアルディスパッチキューに入れます。これにより、2つの操作が同時に発生しないようにします。 「並行処理プログラミングガイド」の"Eliminating Lock-based Code"を参照してください。

iOS> = 4.3が必要な場合は、同時カスタムキューとdispatch barriersを突然変異操作に使用できます。これにより、読み込みが同時に行われるようになりますが、書き込みが必要な場合は書き込みが終了するまで保持されます。バリヤとしてサブミットされたブロックは、基本的に並行キュー上で連続して実行されます。前のブロックがすべて終了するまで開始されず、バリアブロックが完了するまで後続のブロックが開始されません。 (これはジャスティンが言及している読み書きロックのGCD版です)私はsamples of thisのために不可解なマイク・アッシュにあなたを導いています。

+1

正常に終了すると、これにより、パラレルリーダと非ブロッキングライタが可能になります。それは間違いなく今日の好ましい解決策です。 –

2

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

5

最も簡単な方法は、このように、@synchronizedを使用することです:

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

EDIT:ARCを使用していない場合は、あなたは(/オブジェクトを自動解放、それ以外の場合は、配列から削除される可能性があります保持したい場合がありますそして解放された)someMessageが呼び出される前に(この優秀なコメントのためにomzに感謝します)。

+0

Xcodeは@synchronizedをキーワードとして認識しませんが、Xcodeは引き続き動作します。 –

+0

ARCを使用しない場合は、オブジェクトを '保持 'または' autorelease'したいかもしれません。そうでなければ 'someMessage'が呼び出される前に配列から取り除かれ(解放されるかもしれません。 – omz

+0

@omzありがとう、これは非常に重要なコメントです!このような「小さなもの」は、私の人生がARCの下でどのくらい簡単になったのかをより深く理解するのに役立ちます。 – dasblinkenlight

関連する問題