@synchronized (self.class) {
fetchedObjects = [moc executeFetchRequest:request error:&error];
}
moc is a managedObjectContext
It ca
The moc is holding its own lock so you have a lock in a lock -- now when t1 comes, he gets lock 1 but maybe not lock because somebody is fetching already and has lock2 but that one is blocked by t1 (which is waiting)
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.