2

I understand that NSMutableArray shouldn't be trusted to be thread-safe, but what if I only call [array addObject:object] and I'm not accessing the array any other way while doing so?

For example:

NSMutableArray* array = [[NSMutableArray alloc] init];
[self.subviews
  enumerateObjectsWithOptions:NSEnumerationConcurrent
  usingBlock:^(UIView* view, NSUInteger idx, BOOL *stop) {
    if ([self methodThatReturnsBool:view]) [array addObject:view];
  }];

Thanks for any advice! :)

aleclarson
  • 18,087
  • 14
  • 64
  • 91
  • 1
    I disagree. I'm specifically asking about `addObject:`, not the whole `NSMutableArray` class. But I can see why you could think that, since the answer is the same for both (although I wasn't sure if that was true, which is why I asked the question). I've read the answer to that question before, and it wasn't enough for me. – aleclarson Apr 16 '14 at 01:35
  • Can't add my answer - question "closed". Despite docs and answers, my tests show that NSMutableArray never hang, crash, or fail or add an object this way. (strain-tested over millions-of-items loops). Important point though. If this works, it means one thing: addObject: is synchronising on the underlying CFArray data buffers - which means, there is no big gain in "attacking it" from multiple threads. The method will add items one at a time. So - you could as well go safe, and dispatch the addObject: call onto a serial queue. Measure performance, and be well. – Motti Shneor Oct 13 '20 at 08:04
  • BTW you're absolutely right - this is a different question than the one referenced - in a different realm. It's about the actual implementation of NSMutableArray I voted for this question, as I had it myself. – Motti Shneor Oct 13 '20 at 08:07

2 Answers2

2

NSMutableArray is not guaranteed to be thread-safe — not even just adding objects, because making that thread-safe would require addObject: to be an atomic operation, which is not part of the class's contract.

In general, if the documentation says "This is thread-safe," it is thread-safe (at least in isolation), but if the docs don't say that, you should assume it is unsafe and you need to use synchronization.

Chuck
  • 234,037
  • 30
  • 302
  • 389
1

As Bryan Chen pointed out, the NSEnumerationConcurrent thread will cause the block to be run on different threads "at the same time". Modifying an NSMutableArray cannot be done at the same time, from different threads.

Apple's documentation says https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html#//apple_ref/doc/uid/10000057i-CH12-SW1 says that "In most cases, you can use these classes from any thread as long as you use them from only one thread at a time."

So, in your case, you should not do what you are trying to do.

Neil
  • 1,813
  • 1
  • 12
  • 20