0

我正在使用 Core Data 编写一个多线程应用程序。

我的印象是- [NSManagedObjectContext lock]不能作为标准锁使用。作为概念证明,这里是在 Xcode 3“命令行工具”模板之后构建的示例,“核心数据”风格:

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 的实例而不是上下文,死锁会按预期发生)


这是Apple 文档中关于 NSManagedObjectContext 锁的摘录

尝试获取接收器上的锁定。

- (void)lock

讨论

此方法会阻止线程的执行,直到可以获取锁为止。应用程序通过要求线程在执行代码之前获取锁来保护代码的关键部分。一旦临界区过去,线程通过调用解锁来放弃锁定。

将此消息发送到托管对象上下文有助于框架了解多线程环境中事务的范围。最好使用 NSManagedObjectContext 的 NSLocking 实现,而不是使用单独的互斥对象。

如果您锁定(或成功尝试锁定)托管对象上下文,则进行锁定调用的线程必须具有保留,直到它调用解锁。如果在多线程环境中没有正确保留上下文,这将导致死锁。

可用性 适用于 Mac OS X v10.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 回答