はい、@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;
});
このアプローチにより、排他的なライターを使用して無制限の並列リーダーが可能になり、ライターが不足することはなく、書き込みと読み取りがシリアル化されます。実際の競合がない限り、カーネル呼び出しは回避されます。非常に高速でシンプルだと言っても過言ではありません。
リーダーが来ると、値を読み取る要求をキューに入れ、処理されるのを待ちます。ライターが来ると、それを更新するためのバリア要求をキューに入れます。これには、そのキューからの他の要求が現在実行されていないことが必要です。この構成を使用すると、開発者はロックを管理する必要がありません。実行したい順序でキューに入れるだけです。