16

私は経験豊富な.NETプログラマーであり、iOSで足を伸ばしています。.NETで私のお気に入りのマルチスレッド構造の1つは、ReaderWriterLockです。複数のリーダーまたは単一のライターが可能です。私がiOSで本当に欠けている機能の1つは、ロックが再入可能であるということです。つまり、リーダースレッドは、同じ回数だけ読み取りロックを解放する限り、読み取りロックを複数回取得できます。同様に、単一のライタースレッドは、同等の数だけロックを解放する限り、ロックを複数回取得できます。

iOSフレームワークを調べましたが、再入可能性を含め、どの構成要素も同じサポートを提供していないようです。また、pthreadライブラリも調べました。rwlockを見つけましたが、再入可能ではありません。

iOSに、再入可能な読み取り/書き込みロックを可能にするものはありますか?

4

2 に答える 2

19

はい、@synchronizedディレクティブは再入可能です。『スレッドプログラミングガイド』の「@synchronizedディレクティブの使用」および「ObjCプログラミング言語でのスレッド」を参照してください。

そうは言っても、iOSでこれを使用することはほとんどありません。ほとんどの場合、リエントラントロックのような非常に重い(遅い)ロックは言うまでもなく、あらゆる種類のロックを回避できます。iOSが手動のスレッド管理とロックよりも好むキューベースのアプローチの詳細については、同時実行プログラミングガイド、特に「スレッドからの移行」セクションを参照してください。

たとえば、Grand Central Dispatchを使用すると、リーダー/ライターロックは次のように機能します。

- (id)init {
   ...
   _someObjectQueue = dispatch_queue_create("com.myapp.someObject", 
                                            DISPATCH_QUEUE_CONCURRENT);
 }

// In iOS 5 you need to release disptach_release(_someObjectQueue) in dealloc,
// but not in iOS 6.

- (id)someObject {
  __block id result;
  dispatch_sync(self.someObjectQueue, ^{
    result = _someObject;
  });
  return result;
}

- (void)setSomeObject:(id)newValue {
  dispatch_barrier_async(self.queue, ^{
    _someObject = newValue;
});

このアプローチにより、排他的なライターを使用して無制限の並列リーダーが可能になり、ライターが不足することはなく、書き込みと読み取りがシリアル化されます。実際の競合がない限り、カーネル呼び出しは回避されます。非常に高速でシンプルだと言っても過言ではありません。

リーダーが来ると、値を読み取る要求をキューに入れ、処理されるのを待ちます。ライターが来ると、それを更新するためのバリア要求をキューに入れます。これには、そのキューからの他の要求が現在実行されていないことが必要です。この構成を使用すると、開発者はロックを管理する必要がありません。実行したい順序でキューに入れるだけです。

于 2012-10-07T19:58:00.287 に答える
2

iOSスレッドプログラミングガイドから:

システムは、POSIXスレッドのみを使用した読み取り/書き込みロックをサポートします。これらのロックの使用方法の詳細については、pthreadのマニュアルページを参照してください。

したがって、pthreadが再入可能性をサポートしていない場合、答えはノーです。

于 2012-10-07T03:45:47.950 に答える