我正在使用Core数据编写多线程应用程序。
我的印象是,- [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;
}这应该会导致死锁,相反,在MacOSX10.6.8或10.7.4下运行时,我得到了以下日志:
2012-07-18 16:53:40.206 test[20004:a0b] hello world! (context=<NSManagedObjectContext: 0x20000df40>)有人能告诉我发生了什么吗?
(如果我使用的是NSLock实例而不是上下文,那么死锁就会像预期的那样发生)
以下是关于NSManagedObjectContext锁的苹果文档的摘录
锁定
试图获取接收器上的锁。
- (void)lock
讨论
此方法将阻止线程的执行,直到获得锁为止。应用程序通过要求线程在执行代码之前获取锁来保护代码的关键部分。一旦关键部分过去,线程就会通过调用解锁来放弃锁。
将此消息发送到托管对象上下文有助于框架理解多线程环境中事务的范围。最好使用NSManagedObjectContext的NSLocking实现,而不是使用单独的互斥对象。
如果您锁定(或成功地tryLock)一个托管对象上下文,那么发出锁调用的线程必须保持不变,直到它调用解锁为止。如果在多线程环境中没有正确地保留上下文,就会导致死锁。
MacOSXv10.4及更高版本的可用性。
发布于 2012-07-18 15:51:29
似乎由于一个未知的原因,在同一个线程中发生的后续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。
https://stackoverflow.com/questions/11544288
复制相似问题