10

What should be the best way in an iOS app to prevent an instance variable from being changed by an object while another is using it? Should the use of @synchronized(self) directive be enough?

Thanks in advance

Anupdas
  • 10,211
  • 2
  • 35
  • 60
AppsDev
  • 12,319
  • 23
  • 93
  • 186
  • it is instance var, not class var.. and nobody can tell you reliably given only this little info – Daij-Djan Mar 13 '13 at 12:56
  • Is it really a good idea to edit a question ("class variable" --> "instance variable") if one *thinks* that is what the OP meant? From reading his previous question and the answer, it could be that he actually meant "class variable". – Martin R Mar 13 '13 at 13:26
  • Sorry, my fault, I'd have said "static variable", it is a flag whose value I need to be shared between all instances of the class, and ensure that it can be changed only by an instance at a certain time – AppsDev Mar 13 '13 at 16:29
  • Hopefully the answers below help. I think Justin hit the nail on the head. FYI, also see the [Synchronization](http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW1) section of the _Threading Programming Guide._ – Rob Mar 13 '13 at 17:24

3 Answers3

5

If you want that an object is blocked so that no two threads use it at the same time then @synchronize is one way. But this does not make it thread-safe.

You can also use GCD(Grand Central Dispatch) for the same

Community
  • 1
  • 1
Anoop Vaidya
  • 46,283
  • 15
  • 111
  • 140
  • 1
    I assumed that `@synchronize` (or one of the other myriad synchronization mechanisms) was used precisely to make it thread-safe. Admittedly, if you do it wrong, it won't work. And, yes, there are better ways to achieve thread safe code (a la [Tips for Thread Safety](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW6)). But regardless, can you clarify your point that `@synchronize` does not make it thread safe? I thought that was the entire purpose of synchronization techniques. – Rob Mar 13 '13 at 15:51
  • @Rob: At last, I find it here. Also I learnt this in an interview :p – Anoop Vaidya Mar 13 '13 at 16:34
  • 1
    Oh I missed to paste :p http://stackoverflow.com/questions/10853529/locking-an-object-from-being-accessed-by-multiple-threads-objective-c – Anoop Vaidya Mar 13 '13 at 16:39
  • 1
    Great. I'm actually familiar with that post (I'm one of the "up votes" for it). I actually think the accepted answer is misleading on the first point ("fold 1"), regarding the thread-safety, as he focuses on "use the same synchronization token" (well, duh). Bottom line, my understanding is that `@synchronize` _can_ be used to ensure thread safety, though as that post (and my link above) attest, there are better ways to do it. It's not like the common misunderstanding that `atomic` ensures thread safety (which it doesn't). `@synchronize` can, but there are just better ways. Semantics, I guess. – Rob Mar 13 '13 at 16:57
  • 1
    yes i agree with you, for atomic, i posted a question http://stackoverflow.com/questions/12347236/which-is-threadsafe-atomic-or-non-atomic :) – Anoop Vaidya Mar 13 '13 at 16:59
4

What should be the best way in an iOS app to prevent an instance variable from being changed by an object while another is using it?

A good old lock, such as pthread_mutex; you could also use an Objective-C wrapper of this (e.g. NSLock and NSRecursiveLock). @synchronized also falls into this category, but it is the highest level mechanism mentioned here.

Of course, superior concurrent solutions typically have more to do with changes to design, program flow, favoring immutability, and so on. There will still be cases where mutual exclusion/locking is preferred or required.

Unfortunately, pure ObjC/Cocoa are sorely lacking in this domain -- developing a highly efficient concurrent program using ObjC and Cocoa technologies alone is far more difficult than it should be (or needs to be).

Should the use of @synchronized(self) directive be enough?

For simple cases, it is adequate. It is an object level Recursive Lock.

However, it is quite slow, compared to other mutual exclusion options.

I don't think @synchronized has much going for it, apart from:

  • convenience for the developer to introduce (can have bad side-effects) and
  • symmetry (it ensures an unlock matches a lock), greatly reducing the probability of deadlock compared to alternatives (a very good attribute).

@synchronized is convenient, but because it has a high cost, it should be used judiciously.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
justin
  • 104,054
  • 14
  • 179
  • 226
1

If the only purpose is to be able to access

self.myString; //getter

and,

self.myString=aString; //setter

The best way is to declare it as atomic, for example:

@property (atomic, strong) NSString* myString;

This will ensure that in a multithreaded environment, setting and getting myString by thread 1 is protected from thread 2 doing something to it.

Khaled Barazi
  • 8,681
  • 6
  • 42
  • 62