Is it safe to manipulate objects created by me outside of my stream if I don't get them explicitly in the stream that created them?

I am working on cocoa software and in order to support a flexible user interface during mass data import (Core Data), I need to start the import outside the main stream.

Is it safe to access these objects, even if I created them in the main thread without using locks , if I cannot explicitly access these objects while the thread is running.

+3
source share
7 answers

With the underlying data, you must have a separate managed entity context that will be used for the import stream associated with the same coordinator and persistent storage. You cannot just throw objects created in the context used by the main thread into another thread and expect them to work. In addition, you cannot make your own lock for this; you must at least block the context of the managed entity in which the entities reside. But if these objects are associated with your views with controls, there are no “hooks” that you can add that lock the context.

There is no free lunch.

Ben Trumbull explains some reasons why you need to use a separate context and why “just reading” is not as easy or safe as you think in this great post from the end of 2004 on the webobjects-dev list . (The whole stream is wonderful.) He discusses Enterprise Objects Framework and WebObjects, but his advice is fully applicable to Core Data. Just replace “EC” with “NSManagedObjectContext” and “EOF” with “Master Data” in the meat of his message.

The solution to the problem of sharing data between threads in Core Data, like the Framework Enterprise Objects in front of it, is no. If you thought about this further, and you really need to honestly share data between streams, then the solution is to save independent graphic objects in thread-isolated environments and use the information in a save notification from one context to tell you in another context what you need repeat. -[NSManagedObjectContext refreshObject:mergeChanges:] specifically designed to support this use.

+4
source

I believe this is not safe to do with NSManagedObjects (or subclasses) that CoreData NSManagedObjectContext manages. In general, CoreData can perform many complex actions using managed objects, including crash errors associated with these objects in separate threads. In particular, [NSManagedObject initWithEntity:insertIntoManagedObjectContext:] (the designated initializer for NSManagedObjects with OS X 10.5) does not guarantee that the returned object is safe to transmit to another thread.

Using CoreData with multiple threads is well documented on the Apple dev site .

+1
source

The whole point of using locks is to ensure that two threads do not try to access the same resource. If you can guarantee that through some other mechanism, go for it.

0
source

Even if it is safe, it is not recommended to use shared data between threads without synchronizing access to these fields. It does not matter which thread created the object, but if several instances of execution (thread / process) access the object at the same time, as this can lead to data inconsistency.

If you are absolutely sure that only one thread will ever access this object, then it would be safe not to synchronize access. Even then, I would rather synchronize in my code now than wait until a change in the application places a second thread sharing the same data without worrying about access synchronization.

0
source

Yes, it is safe. A fairly common template is to create an object, then add it to the queue or some other collection. The second “consumer” thread takes items from the queue and does something with them. Here you will need to synchronize the queue, but not the objects that are added to the queue.

You should not just synchronize everything and hope for the best. You will need to think carefully about your design and exactly what flows can affect your objects.

0
source

Yes you can do it, it will be safe

... until the second programmer appears and understands the same assumptions that you made. This second (or 3rd, 4th, 5th, ...) programmer is likely to start using the object in an unsafe way (in the thread of the creator). Caused problems can be very subtle and difficult to track. For this reason alone and because it is so tempting to use this object in multiple threads, I would make the object a thread safe.

To clarify (thanks to those who left comments):

By "thread safe" I mean programmatically designing a circuit to avoid threading issues. I do not necessarily want to develop a locking scheme around your object. You could find a way in your language to make it illegal (or very difficult) to use the object in the creator thread. For example, restricting the scope in the creator stream to a block of code that creates an object. After creating, pass the object to the user stream, making sure that the creator stream no longer refers to it.

For example, in C ++

 void CreateObject() { Object* sharedObj = new Object(); PassObjectToUsingThread( sharedObj); // this function would be system dependent } 

Then, in your creation stream, you no longer have access to the object after its creation, responsibility is transferred to the used stream.

0
source

Two things to consider:

  • You must be able to ensure that the object is fully created and initialized before it becomes available to other threads.
  • There must be some mechanism by which the main (GUI) stream detects that the data is loaded, and everything is fine. To be thread safe, this will inevitably lead to some kind of blocking.
0
source

All Articles