NSManagedObjectContext and any associated managed objects must be bound to a single player (thread, serialized queue, NSOperationQueue with max concurrency = 1).
This pattern is called restriction or isolation of flows. There is no big phrase for (thread || serialized queue || NSOperationQueue with max concurrency = 1), so the documentation goes on to say: βWe will use theβ thread βfor the rest of the Core Data document when we mean any of these three methods of getting serialized control flow "
If you create a MOC in one thread and then use it on another, you violated the flow restriction by exposing the MOC object reference to two threads. Simply. Do not do this. Do not cross streams.
We explicitly call NSOperation because, unlike threads and GCD, this problem has such a strange problem when -init works in a thread that creates NSOperation, but -main works in a thread that performs NSOperation. It makes sense if you evaluate it correctly, but it is not intuitive. If you create your MOC in [NSOperation init], NSOperation will effectively violate the flow restriction before your -main method is even started and you are closed.
We actively discourage / refuse to use MOC and flows in any other way. Although it is theoretically possible to do what is mentioned in bbum, no one understood. Everyone stumbled, forgot the right call for -lock in 1st place, "init starts where?" Or otherwise cleaned himself up. With autocomplete pools and an application event loop and undo manager and cocoa and KVO bindings, there are only so many ways that one thread maintains a link to the MOC after you try to pass it to another location. This is much more complicated than even advanced cocoa developers until they start debugging. So not a very useful API.
The documentation has changed to clarify and emphasize the flow restriction pattern as the only normal way. You should consider trying to be extravagant using -lock and -unlock in NSManagedObjectContext to be (a) impossible and (b) de facto deprecated. This is not literally not recommended, because the code works as well as ever. But your code uses it incorrectly.
Some people created MOC on 1 thread and passed them to another without causing -lock. It was never legal. The thread that created the MOC was always the owner of the MOC by default. This has become a more frequent problem for MOCs created in the main thread. The main MOC thread interacts with the main application event loop for cancellation, memory management, and some other reasons. On 10.6 and iOS 3, MOCs take a more proactive advantage in that they belong to the main thread.
Although the queues are not tied to specific threads, if you create the MOC in the context of the queue, everything will be correct. Your responsibility is to follow the public API.
If the queue is serialized, you can share the MOC with subsequent blocks that run in this queue.
Therefore, do not expose NSManagedObjectContext * to more than one thread (actor, etc.) under any circumstances. There is one ambiguity. You can pass NSNotification * from the didSave notification to another MOC stream -mergeChangesFromContextDidSaveNotification: method.