What happens if NSMutableArray is modified by multiple threads at the same time? (if the objects contained in it are saved elsewhere)

I have an NSMutableArray containing many objects.

What happens if I make changes to the array while I make a copy of the array using [NSMutableArray arrayWithArray: someArray];

For example: if the object is deleted from the array during copying?

I am not sure how to test this scenario.

EDIT: objects are not freed (as they are stored elsewhere). I just use this array as a lookup table.

+6
source share
3 answers

as you know, container / collection is not guaranteed by flow. What can happen if you change the array while copying or reading? many things. the obvious case is that it can be redistributed at that time, it can transfer or return an invalid link to you (for example, a recently deleted one), or it can have access to objects that were released (from another stream). in addition to causing your application to crash or calling another UB, it may not return the correct or consistent values. this is a misinterpretation of data. neither good nor good.

you don’t check the scenario - threading problems are hard to reproduce and you really can never cover all cases. since the object itself does not guarantee thread safety - your implementation should limit access / mutations / interactions to one thread at a time. when working with an object that is used in multi-threaded contexts: at any time when you gain access or request information from a mutable object, you must protect the object (for example, by using a lock). so you just block it when using it. lock / copy / unlock / use copy is also regular mail. for NSMutableArray, examples of mutable state are all its objects and their score. its operations and mutations also use a mutable object, so they are limited.

if you use this object from only one thread, then obviously it does not need to be blocked. this is also the reason that forwarding and storing immutable options in most cases are good ideas. you do not need a lock for each object, protection for the object that contains it is often a good way to create a thread safety class.

Update

... What's happening? The copy contains all 5 objects (since they are still left in another place? Do they contain 4? (Even 4 is enough for me). Is an exception thrown?

if you didn’t properly guard the collection, this is as good as undefined behavior, and you are lucky if it works.

You need to take appropriate precautions to avoid undefined behavior. your program runs in this domain if it is not properly protected.

to clarify: saving objects from the outside only reduces the likelihood of undefined behave \ ior, but this, of course, does not eliminate it. more examples of consequences include exceptions, segfaults, reading or writing memory, which is used as another active allocation (which can manifest itself as very mysterious problems, which can also be almost impossible to reproduce).

I recommend that you guard or use a different approach. UB - EVIL :)

+11
source

From Apple Docs :

Variable objects are generally not thread safe. To use mutable objects in a threaded application, the application must synchronize access to them using locks. (For more information, see "Atomic Operations"). In general, collection classes (e.g. NSMutableArray, NSMutableDictionary) are not thread safe when mutating. That is, if one or more threads change the same array, problems can arise. You must block the places where you are reading and writing to ensure the safety of the stream.

Also from Apple Docs :

Although “atomic” means that access to a property is thread-safe, just creating all the properties in your atom class does not mean that your class or the more general graph of the object is “thread-safe” -security cannot be expressed at the individual access methods level. For more information on multithreading, see Thread Programming Guide.

+5
source

If removeObject is called at the same time as arrayWithArray, your program will crash. If you use synchronization, forced deletion of the deletion object must be performed either immediately before or immediately after arrayWithArray, you cannot know how many objects the new array will have. It doesn't crash right away, but what will your code do? You should be very clear in your mind that the result of [NSArray arrayWithArray: someArray] is an array that does not contain someArray contents right now, and someArray contents at some point in the past.

0
source

Source: https://habr.com/ru/post/896709/


All Articles