0

I am designing a singleton class in Objective-C which will be accessed by multiple threads. There are 3-4 NSMutableArrays in my class, outside classes have access with read, add and remove operations which is of course wrapped in this class.

As NSMutableArray is not thread safe, I am using @synchronized() to make my operations thread safe, however it causes too much usage of @synchronized() blocks.

Because for 3-4 array for each I have at least 1 add function, 1 remove function and 5 times I need to read the values. So, for 1 array I am using at least 7 @synchronized() blocks. For 4 arrays, I need to add 28 @synchronized blocks in my singleton class.

Is there any better way to approach my problem? or, If I do use too all these @synchronized directives, will it causes problem ?

I know that if I want to make my objects thread safe it will slow down my code, but besides that is there any drawback?

jscs
  • 63,694
  • 13
  • 151
  • 195
taserghar
  • 340
  • 3
  • 15
  • 1
    1) If your singleton is thread safe then you probably don't need to worry about its data members, _NSMutableArray_ in your case. 2) You must have heard of and used _atomic/nonatomic_ attributes of the data members. The former makes them thread safe. For extra security you can declare your _NSMutableArrays_ to be atomic. – Adeel Miraj Feb 23 '17 at 07:08
  • 1
    Another approach is to create a serial dispatch queue for each array. You can then dispatch array updates synchronously onto the relevant queue in your array update methods. @Adeel, making an NSMutable array property atomic will not make the underlying array threadsafe, merely the property itself. – Paulw11 Feb 23 '17 at 07:24
  • 1
    @Adeel: Using the atomic attribute for a property that's a mutable object type does _absolutely nothing_ to synchronize mutations. It does not make it "thread safe". It does one thing and one thing only: it ensures that the getter and setter are not interrupted. What happens with the object after that is not controlled. – jscs Feb 23 '17 at 13:12
  • @Adeel , how to make a perfect thread safe singleton class? I just made my initialization with dispatch once guard. And tried to add synchronization in my critical section where I am accessing MutableArrays. And I also don't think using atomic attribute make my array threadsafe. – taserghar Feb 24 '17 at 01:52

1 Answers1

2

Typically it is not sufficient to just synchronize the primitive calls (CRUD) to gain thread safety. This fine granular level is just the basic, but you'll also have to think on a more global level and "atomize" larger amounts of code. How to do this is highly dependend on your actual implementation. Multithreading is evil(tm) and demands a comprehensive view, so there is no general answer for this.

Synchronized blocks will typically slow down your application, at least if they are called too frequently. Sometimes it's better to group multiple calls in one synchronized block, to avoid the locking overhead. Or you could use spin locks, if the calls are very short, to prevent unnecessary task suspensions (see here for an old question/answer).

For more details you can just consult the Apple documentation.

Community
  • 1
  • 1
Andreas Oetjen
  • 9,889
  • 1
  • 24
  • 34
  • I am new in objective c, I worked in linux, do spin lock and objective c mutex are similar to pthread_mutex_lock ? there is a trade off of using **synchronized** and pthread_mutex_lock because **synchronized** don't lock code within same thread or function stack where pthread_mutex_lock can lock within the same thread and function call stack. there is another benefits of **synchronized** you can use **return** from whenever you want within the block, it will automatically unlock. But using pthread_mutex_lock it will make your life hell if you miss any of the condition. – taserghar Feb 23 '17 at 09:37
  • 1
    I think details have already been ansered here: http://stackoverflow.com/questions/9463525/pthread-mutex-t-vs-synchronized-block - Spin Locks are quite different, because the cause "active" waiting and are only recommanded upon very short calls. – Andreas Oetjen Feb 23 '17 at 13:23
  • Thanks for your answer.I am sorry I forgot to mention about iOS where spin lock will be a bad idea. I think for my scenario, as you suggested, recursive mutex will be more appropriate. – taserghar Feb 25 '17 at 11:19