这是怎么造成死锁的(一段时间内),我该如何解开 [英] How does this cause deadlock (once in a while) and how do I unravel this

查看:103
本文介绍了这是怎么造成死锁的(一段时间内),我该如何解开的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

@synchronized (self.class)     {
    fetchedObjects = [moc executeFetchRequest:request error:&error];
}

moc是managedObjectContext

可能是与主线程相对应的Moc.该moc是所有MOC的父项.

其他人只是孩子.有时,当孩子执行executeFetchRequest时,也会使父级Moc执行相同的executeFetchRequest.

我经常看到的是

外部主线程:

@synchronized (self.class)     {
    fetchedObjects = [moc executeFetchRequest:request error:&error]; //semaphore_wait_trap here
}

在主线程上

@synchronized (self.class)     {//_psynch_mutexwait
    fetchedObjects = [moc executeFetchRequest:request error:&error];
}

好吧...为什么会陷入僵局?即使主线程上的moc与主线程相对应,也根本没有访问它.它在@synchronized等待.那么为什么要fetchedObjects = [moc executeFetchRequest:request error:&error];等待呢?

解决方案

您不应@synchronizeing调用executeFetchRequest:

executeFetchRequest:error:方法本质上可以根据硬件和工作负载来扩展其行为.如有必要,Core Data将创建其他私有线程以优化获取性能.为此,您不会通过创建后台线程来提高绝对获取速度.但是,仍然可以在后台线程或队列中进行提取以防止应用程序的用户界面被阻塞.这意味着,如果获取操作很复杂或返回大量数据,则可以将控制权返回给用户并在结果到达时显示它们.

《核心数据编程指南:并发性》

基本上,如果要返回很多对象并对其进行处理,则最好从私有队列上下文中执行此操作(因为然后可以在该私有队列上使用返回的对象并从主队列中对其进行处理). /p>

如果您有主队列上下文,请仅在主队列中使用它.

此外,子上下文通过将获取请求传递给其父母来执行获取请求.发生的事情(据我所知)是,该谓词在持久性存储(SQL)以及链中每个MOC中未保存的对象上进行求值.这意味着,例如,如果您覆盖谓词中使用的getter,则会在内存中那些未保存的对象上调用它(而SQL谓词使用原始DB值进行比较).您可以通过从子上下文中阻止其父队列来使该父上下文死锁.

@synchronized (self.class)     {
    fetchedObjects = [moc executeFetchRequest:request error:&error];
}

moc is a managedObjectContext

It can be the moc that correspond to the main thread. That moc is the parent of all MOC.

The other moc are just children. Sometimes when the child do executeFetchRequest it will also make the parent moc do the same executeFetchRequest.

What I often see is

outside main thread:

@synchronized (self.class)     {
    fetchedObjects = [moc executeFetchRequest:request error:&error]; //semaphore_wait_trap here
}

On main thread

@synchronized (self.class)     {//_psynch_mutexwait
    fetchedObjects = [moc executeFetchRequest:request error:&error];
}

Okay... Why the deadlock? Even though the moc on main thread correspond to the main thread it's not being accessed at all. It wait at @synchronized. So why fetchedObjects = [moc executeFetchRequest:request error:&error]; wait?

解决方案

You shouldn't be @synchronize-ing calls to executeFetchRequest:

The executeFetchRequest:error: method intrinsically scales its behavior appropriately for the hardware and work load. If necessary, the Core Data will create additional private threads to optimize fetching performance. You will not improve absolute fetching speed by creating background threads for the purpose. It may still be appropriate, however, to fetch in a background thread or queue to prevent your application’s user interface from blocking. This means that if a fetch is complicated or returns a large amount of data, you can return control to the user and display results as they arrive.

Core Data Programming Guide: Concurrency

Basically if you're returning a lot of objects and processing them, it's best to do that from a private queue context (since you can then use the returned objects on that private queue and process them off the main queue).

If you have a main queue context, only use it from the main queue.

Also, child contexts execute fetch requests by passing them to their parents. What happens (from what I can tell) is that the predicate gets evaluated on the persistent store (SQL), and on the unsaved objects in each MOC in the chain. This means that if you, say, override a getter that is used in a predicate, it will be called on those unsaved objects in memory (whereas the SQL predicate uses the raw DB values to compare against). You can deadlock a parent context by blocking its queue from a child context.

这篇关于这是怎么造成死锁的(一段时间内),我该如何解开的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆