0

CoreDataを使用してマルチスレッドアプリケーションを作成しています。

- [NSManagedObjectContext lock]標準のロックとしては機能しないという印象を受けています。概念実証として、Xcode3の「コマンドラインツール」テンプレートである「CoreData」フレーバーの後に作成されたサンプルを次に示します。

int main (int argc, const char * argv[])
{
  objc_startCollectorThread();

  NSManagedObjectContext *context = managedObjectContext();

  [context lock];
  [context lock];

  NSLog(@"hello world! (context=%@)", context);

  [context unlock];
  [context unlock];

  return 0;
}

Mac OS X 10.6.8または10.7.4で実行している場合、代わりにデッドロックが発生するはずです。次のログがあります。

2012-07-18 16:53:40.206 test[20004:a0b] hello world! (context=<NSManagedObjectContext: 0x20000df40>)

誰かが何が起こっているのか教えてもらえますか?

(コンテキストの代わりにNSLockのインスタンスを使用すると、デッドロックは予想どおりに発生します)


これは、 NSManagedObjectContextロックに関するAppleドキュメントからの抜粋です。

ロック

受信機のロックを取得しようとします。

- (void)lock

討論

このメソッドは、ロックを取得できるようになるまでスレッドの実行をブロックします。アプリケーションは、コードを実行する前にスレッドにロックの取得を要求することにより、コードのクリティカルセクションを保護します。クリティカルセクションが過ぎると、スレッドはロック解除を呼び出してロックを解放します。

このメッセージを管理対象オブジェクトコンテキストに送信すると、フレームワークがマルチスレッド環境でのトランザクションのスコープを理解するのに役立ちます。別のミューテックスオブジェクトを使用する代わりに、NSManagedObjectContextのNSLockingの実装を使用することをお勧めします。

管理対象オブジェクトコンテキストをロック(または正常にtryLock)する場合、ロック呼び出しが行われるスレッドは、ロック解除を呼び出すまで保持する必要があります。マルチスレッド環境でコンテキストを適切に保持しないと、デッドロックが発生します。

可用性MacOSXv10.4以降で利用できます。

4

1 に答える 1

0

不明な理由により、同じスレッドで発生した場合、後続のNSManagedObjectロックは無視されるようです。

期待どおりに機能する別のサンプルコードを次に示します(実行時にログがありません)。

@implementation NSManagedObjectContext (Test)
- (void)testLock:(id)sender
{
  [self lock];

  NSLog(@"hello world! (context=%@)", self);

  [self unlock];
}
@end

int main (int argc, const char * argv[])
{
  objc_startCollectorThread();

  NSManagedObjectContext *context = managedObjectContext();

  [context lock];

  [NSThread detachNewThreadSelector:@selector(testLock:) toTarget:context withObject:nil];

  sleep(2);
}

ノート:

- (BOOL)[NSManagedObjectContext tryLock]YESまた、後続の呼び出しに対しても戻ります。

于 2012-07-18T15:51:29.823 に答える