【问题标题】:NSManagedObjectContext lockNSManagedObjectContext 锁
【发布时间】:2012-07-18 14:56:21
【问题描述】:

我正在使用 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 Documentation about NSManagedObjectContext lock的摘录

锁定

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

- (void)lock

讨论

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

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

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

可用性 适用于 Mac OS X v10.4 及更高版本。

【问题讨论】:

    标签: multithreading macos core-data locking


    【解决方案1】:

    似乎由于未知原因,在同一线程中发生后续 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 用于任何后续调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-28
      • 2012-02-06
      • 2015-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多